mirror of
https://github.com/internetee/registry.git
synced 2025-06-10 22:54:47 +02:00
Fully implemented prepayment Directo invoice forwarding, WIP on proformas
This commit is contained in:
parent
faeb50cad5
commit
d5662f42b8
10 changed files with 249 additions and 337 deletions
12
Gemfile.lock
12
Gemfile.lock
|
@ -7,6 +7,15 @@ GIT
|
|||
activesupport
|
||||
savon
|
||||
|
||||
GIT
|
||||
remote: https://github.com/internetee/directo.git
|
||||
revision: 6ac71939da589fcceb5ef3989ba982134679ec97
|
||||
branch: directo-api
|
||||
specs:
|
||||
directo (0.1.0)
|
||||
money (~> 6.13)
|
||||
nokogiri (~> 1.10)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/internetee/e_invoice.git
|
||||
revision: 3a754974ed25569aa85d99a87ae9e131b7c10a24
|
||||
|
@ -457,6 +466,7 @@ DEPENDENCIES
|
|||
database_cleaner
|
||||
devise (~> 4.7)
|
||||
digidoc_client!
|
||||
directo!
|
||||
domain_name
|
||||
e_invoice!
|
||||
epp!
|
||||
|
@ -500,4 +510,4 @@ DEPENDENCIES
|
|||
wkhtmltopdf-binary
|
||||
|
||||
BUNDLED WITH
|
||||
2.0.2
|
||||
2.1.4
|
||||
|
|
99
app/controllers/concerns/book_keeping.rb
Normal file
99
app/controllers/concerns/book_keeping.rb
Normal file
|
@ -0,0 +1,99 @@
|
|||
module BookKeeping
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI',
|
||||
'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze
|
||||
|
||||
def monthly_summary(month:)
|
||||
activities = monthly_activites(month)
|
||||
inv = {
|
||||
'number': 1,
|
||||
'customer_code': accounting_customer_code,
|
||||
'language': language,
|
||||
'currency': activities.first.currency,
|
||||
'date': month.end_of_month.strftime('%Y-%m-%d'),
|
||||
}.as_json
|
||||
|
||||
lines = []
|
||||
activities.each do |activity|
|
||||
fetch_invoice_lines(activity, lines)
|
||||
end
|
||||
lines << prepayment_for_all(lines)
|
||||
|
||||
inv['invoice_lines'] = lines.as_json
|
||||
|
||||
inv
|
||||
end
|
||||
|
||||
def fetch_invoice_lines(activity, lines)
|
||||
price = load_price(activity)
|
||||
if price.duration.include? 'year'
|
||||
price.duration.to_i.times do |duration|
|
||||
lines << new_montly_invoice_line(activity: activity, duration: duration + 1).as_json
|
||||
end
|
||||
else
|
||||
lines << new_monthly_invoice_line(activity: activity).as_json
|
||||
end
|
||||
end
|
||||
|
||||
def monthly_activites(month)
|
||||
AccountActivity.where(account_id: account_ids)
|
||||
.where(created_at: month.beginning_of_month..month.end_of_month)
|
||||
.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW])
|
||||
end
|
||||
|
||||
def new_montly_invoice_line(activity:, duration: nil)
|
||||
price = DirectoInvoiceForwardJob.load_price(activity)
|
||||
yearly = price.duration.include?('year')
|
||||
line = {
|
||||
'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym],
|
||||
'quantity': 1,
|
||||
'price': yearly ? (price.price.amount / price.duration.to_i) : price.amount,
|
||||
}
|
||||
|
||||
line['description'] = description_in_language(price: price, yearly: yearly)
|
||||
add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1
|
||||
|
||||
line
|
||||
end
|
||||
|
||||
def add_product_timeframe(line:, activity:, duration:)
|
||||
create_time = activity.created_at
|
||||
line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d')
|
||||
line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d')
|
||||
end
|
||||
|
||||
def description_in_language(price:, yearly:)
|
||||
if language == 'en'
|
||||
registration_length = yearly ? 'year' : 'month'
|
||||
prefix = ".#{price.zone_name} registration: #{price.duration.to_i} #{registration_length}"
|
||||
suffix = 's'
|
||||
else
|
||||
registration_length = yearly ? 'aasta' : 'kuu'
|
||||
prefix = ".#{price.zone_name} registreerimine: #{price.duration.to_i} #{registration_length}"
|
||||
suffix = yearly ? 't' : 'd'
|
||||
end
|
||||
|
||||
return "#{prefix}#{suffix}" if price.duration.to_i > 1
|
||||
|
||||
prefix
|
||||
end
|
||||
|
||||
def prepayment_for_all(lines)
|
||||
total = 0
|
||||
lines.each { |l| total += l['quantity'].to_f * l['price'].to_f }
|
||||
{
|
||||
'product_id': Setting.directo_receipt_product_name,
|
||||
'description': 'Domeenide ettemaks',
|
||||
'quantity': -1,
|
||||
'price': total
|
||||
}
|
||||
end
|
||||
|
||||
def load_price(account_activity)
|
||||
@pricelists ||= {}
|
||||
return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id
|
||||
|
||||
@pricelists[account_activity.price_id] = account_activity.price
|
||||
end
|
||||
end
|
101
app/jobs/directo_invoice_forward_job.rb
Normal file
101
app/jobs/directo_invoice_forward_job.rb
Normal file
|
@ -0,0 +1,101 @@
|
|||
class DirectoInvoiceForwardJob < Que::Job
|
||||
def run(monthly: false, dry: false)
|
||||
@dry = dry
|
||||
api_url = ENV['directo_invoice_url']
|
||||
sales_agent = Setting.directo_sales_agent
|
||||
payment_term = Setting.directo_receipt_payment_term
|
||||
@prepayment_product_id = Setting.directo_receipt_product_name
|
||||
|
||||
@client = DirectoApi::Client.new(api_url, sales_agent, payment_term)
|
||||
monthly ? send_monthly_invoices : send_receipts
|
||||
end
|
||||
|
||||
def send_receipts
|
||||
unsent_invoices = Invoice.where(in_directo: false).non_cancelled
|
||||
|
||||
Rails.logger.info("[DIRECTO] Trying to send #{unsent_invoices.count} prepayment invoices")
|
||||
unsent_invoices.each do |invoice|
|
||||
unless valid_invoice_conditions?(invoice)
|
||||
Rails.logger.info "[DIRECTO] Invoice #{invoice.number} has been skipped"
|
||||
next
|
||||
end
|
||||
@client.invoices.add_with_schema(invoice: invoice.as_directo_json, schema: 'prepayment')
|
||||
end
|
||||
|
||||
sync_with_directo
|
||||
end
|
||||
|
||||
def send_monthly_invoices
|
||||
month = Time.now - 1.month
|
||||
|
||||
Registrar.where.not(test_registrar: true).find_each do |registrar|
|
||||
next unless registrar.cash_account
|
||||
|
||||
invoice = registrar.monthly_summary(month: month)
|
||||
@client.invoices.add_with_schema(invoice: invoice, schema: 'summary')
|
||||
end
|
||||
|
||||
# TODO: Invoice number
|
||||
sync_with_directo
|
||||
end
|
||||
|
||||
def valid_invoice_conditions?(invoice)
|
||||
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
|
||||
invoice.account_activity.bank_transaction.sum.nil? ||
|
||||
invoice.account_activity.bank_transaction.sum != invoice.total
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def sync_with_directo
|
||||
Rails.logger.info('[Directo] - attempting to send following XML:')
|
||||
puts @client.invoices.as_xml
|
||||
|
||||
return if @dry
|
||||
|
||||
res = @client.invoices.deliver(ssl_verify: false)
|
||||
|
||||
update_invoice_directo_state(res.body) if res.code == '200'
|
||||
rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
||||
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
|
||||
Rails.logger.info("[Directo] Failed. Responded with code: #{res.code}, body: #{res.body}")
|
||||
end
|
||||
|
||||
def update_invoice_directo_state(xml)
|
||||
Nokogiri::XML(xml).css('Result').each do |res|
|
||||
inv = Invoice.find_by(number: res.attributes['docid'].value.to_i)
|
||||
mark_invoice_as_sent(invoice: inv, data: res)
|
||||
end
|
||||
end
|
||||
|
||||
def mark_invoice_as_sent(invoice:, data:)
|
||||
invoice.directo_records.create!(response: data.as_json.to_h, invoice_number: invoice.number)
|
||||
invoice.update_columns(in_directo: true)
|
||||
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} was pushed and return is #{data.as_json.to_h.inspect}")
|
||||
end
|
||||
|
||||
def self.load_price(account_activity)
|
||||
@pricelists ||= {}
|
||||
if @pricelists.key? account_activity.price_id
|
||||
return @pricelists[account_activity.price_id]
|
||||
end
|
||||
|
||||
@pricelists[account_activity.price_id] = account_activity.price
|
||||
end
|
||||
|
||||
def last_directo_monthly_number
|
||||
min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
|
||||
max_directo = Setting.directo_monthly_number_max.presence.try(:to_i)
|
||||
last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i), min_directo]
|
||||
.compact.max || 0
|
||||
|
||||
if max_directo && max_directo <= last_directo
|
||||
raise 'Directo counter is out of period'
|
||||
end
|
||||
|
||||
last_directo
|
||||
end
|
||||
end
|
|
@ -1,100 +0,0 @@
|
|||
class DirectoInvoiceForwardJobJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(monthly: false, dry: false)
|
||||
api_url = ENV['directo_invoice_url']
|
||||
sales_agent = Setting.directo_sales_agent
|
||||
payment_term = Setting.directo_receipt_payment_term
|
||||
@prepayment_product_id = Setting.directo_receipt_product_name
|
||||
|
||||
@client = DirectoApi::Client.new(api_url, sales_agent, payment_term)
|
||||
monthly ? send_monthly_invoices(dry: dry) : send_receipts(dry: dry)
|
||||
end
|
||||
|
||||
def send_receipts
|
||||
unsent_invoices = Invoice.where(in_directo: false).non_cancelled
|
||||
|
||||
Rails.logger.info("[DIRECTO] Trying to send #{unsent_invoices.count} prepayment invoices")
|
||||
unsent_invoices.each do |invoice|
|
||||
unless valid_invoice_conditions?(invoice)
|
||||
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped") && next
|
||||
end
|
||||
|
||||
@client.invoices.add(generate_directo_invoice(invoice: invoice, client: @client,
|
||||
product_id: @prepayment_product_id))
|
||||
end
|
||||
sync_with_directo
|
||||
end
|
||||
|
||||
def send_monthly_invoices; end
|
||||
|
||||
def valid_invoice_conditions?(invoice)
|
||||
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
|
||||
invoice.account_activity.bank_transaction.sum.nil? ||
|
||||
invoice.account_activity.bank_transaction.sum != invoice.total
|
||||
false
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
def generate_directo_invoice(invoice:, client:, product_id:)
|
||||
inv = client.invoices.new
|
||||
inv = create_invoice_meta(directo_invoice: inv, invoice: invoice)
|
||||
inv = create_invoice_line(invoice: invoice, directo_invoice: inv, product_id: product_id)
|
||||
|
||||
inv
|
||||
end
|
||||
|
||||
def create_invoice_meta(directo_invoice:, invoice:)
|
||||
directo_invoice.customer = create_invoice_customer(invoice: invoice)
|
||||
directo_invoice.date = invoice.issue_date.strftime('%Y-%m-%d') # Mapped
|
||||
directo_invoice.transaction_date =
|
||||
invoice.account_activity.bank_transaction&.paid_at&.strftime('%Y-%m-%d') # Mapped
|
||||
directo_invoice.number = invoice.number # Mapped
|
||||
directo_invoice.currency = invoice.currency # Mapped
|
||||
directo_invoice.language = 'ENG' # Hardcoded
|
||||
|
||||
directo_invoice
|
||||
end
|
||||
|
||||
def create_invoice_line(invoice:, directo_invoice:, product_id:)
|
||||
line = directo_invoice.lines.new
|
||||
line.code = product_id # MAPPED
|
||||
line.description = invoice.result.auction.domain_name # MAPPED
|
||||
line.quantity = 1 # MAPPED
|
||||
line.price = ActionController::Base.helpers.
|
||||
number_with_precision(invoice.subtotal, precision: 2, separator: ".") # MAPPED
|
||||
directo_invoice.lines.add(line)
|
||||
|
||||
directo_invoice
|
||||
end
|
||||
|
||||
def create_invoice_customer(invoice:)
|
||||
customer = Directo::Customer.new
|
||||
customer.code = invoice.buyer.accounting_customer_code # MAPPED
|
||||
|
||||
customer
|
||||
end
|
||||
|
||||
def sync_with_directo
|
||||
res = @client.invoices.deliver(ssl_verify: false)
|
||||
Rails.logger.info("[Directo] Directo responded with code: #{res.code}, body: #{res.body}")
|
||||
update_invoice_directo_state(res.body) if res.code == '200'
|
||||
rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
||||
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
|
||||
Rails.logger.info("[Directo] Failed. Responded with code: #{res.code}, body: #{res.body}")
|
||||
end
|
||||
|
||||
def update_invoice_directo_state(xml)
|
||||
Nokogiri::XML(xml).css('Result').each do |res|
|
||||
inv = Invoice.find_by(number: res.attributes['docid'].value.to_i)
|
||||
mark_invoice_as_sent(invoice: inv, data: res)
|
||||
end
|
||||
end
|
||||
|
||||
def mark_invoice_as_sent(invoice:, data:)
|
||||
invoice.directo_records.create!(response: data.as_json.to_h, invoice_number: invoice.number)
|
||||
invoice.update_columns(in_directo: true)
|
||||
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} was pushed and return is #{data.as_json.to_h.inspect}")
|
||||
end
|
||||
end
|
|
@ -1,24 +0,0 @@
|
|||
class Counter
|
||||
def initialize value = 0
|
||||
@value = value
|
||||
end
|
||||
attr_accessor :value
|
||||
def method_missing *args, &blk
|
||||
@value.send(*args, &blk)
|
||||
end
|
||||
def to_s
|
||||
@value.to_s
|
||||
end
|
||||
|
||||
def now
|
||||
@value
|
||||
end
|
||||
|
||||
# pre-increment ".+" when x not present
|
||||
def next(x = 1)
|
||||
@value += x
|
||||
end
|
||||
def prev(x = 1)
|
||||
@value -= x
|
||||
end
|
||||
end
|
|
@ -1,198 +1,3 @@
|
|||
class Directo < ApplicationRecord
|
||||
DOMAIN_TO_PRODUCT = {"ee" => "01EE", "com.ee" => "02COM", "pri.ee" => "03PRI", "fie.ee"=>"04FIE", "med.ee" => "05MED"}.freeze
|
||||
belongs_to :item, polymorphic: true
|
||||
|
||||
def self.send_receipts
|
||||
new_trans = Invoice.where(in_directo: false).non_cancelled
|
||||
total = new_trans.count
|
||||
counter = 0
|
||||
Rails.logger.info("[DIRECTO] Will try to send #{total} invoices")
|
||||
|
||||
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|
|
||||
|
||||
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
|
||||
invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.total
|
||||
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped")
|
||||
next
|
||||
end
|
||||
counter += 1
|
||||
|
||||
num = invoice.number
|
||||
paid_at = invoice.account_activity.bank_transaction&.paid_at&.strftime("%Y-%m-%d")
|
||||
mappers[num] = invoice
|
||||
xml.invoice(
|
||||
"SalesAgent" => Setting.directo_sales_agent,
|
||||
"Number" => num,
|
||||
"InvoiceDate" => invoice.issue_date.strftime("%Y-%m-%d"),
|
||||
'TransactionDate' => paid_at,
|
||||
"PaymentTerm" => Setting.directo_receipt_payment_term,
|
||||
"Currency" => invoice.currency,
|
||||
"CustomerCode"=> invoice.buyer.accounting_customer_code
|
||||
){
|
||||
xml.line(
|
||||
"ProductID" => Setting.directo_receipt_product_name,
|
||||
"Quantity" => 1,
|
||||
"UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.subtotal, precision: 2, separator: "."),
|
||||
"ProductName" => invoice.order
|
||||
)
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
data = builder.to_xml.gsub("\n",'')
|
||||
Rails.logger.info("[Directo] XML request: #{data}")
|
||||
response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false)
|
||||
Rails.logger.info("[Directo] Directo responded with code: #{response.code}, body: #{response.body}")
|
||||
dump_result_to_db(mappers, response.to_s)
|
||||
end
|
||||
|
||||
STDOUT << "#{Time.zone.now.utc} - Directo receipts sending finished. #{counter} of #{total} are sent\n"
|
||||
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, invoice_number: obj.number)
|
||||
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
|
||||
|
||||
|
||||
def self.send_monthly_invoices(debug: false)
|
||||
I18n.locale = :et
|
||||
month = Time.now - 1.month
|
||||
invoices_until = month.end_of_month
|
||||
date_format = "%Y-%m-%d"
|
||||
invoice_counter= Counter.new
|
||||
|
||||
min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
|
||||
max_directo = Setting.directo_monthly_number_max.presence.try(:to_i)
|
||||
last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i), min_directo].compact.max || 0
|
||||
if max_directo && max_directo <= last_directo
|
||||
raise "Directo counter is out of period (max allowed number is smaller than last counter number)"
|
||||
end
|
||||
|
||||
directo_next = last_directo
|
||||
Registrar.where.not(test_registrar: true).find_each do |registrar|
|
||||
unless registrar.cash_account
|
||||
Rails.logger.info("[DIRECTO] Monthly invoice for registrar #{registrar.id} has been skipped as it doesn't has cash_account")
|
||||
next
|
||||
end
|
||||
counter = Counter.new(1)
|
||||
items = {}
|
||||
registrar_activities = AccountActivity.where(account_id: registrar.account_ids).where("created_at BETWEEN ? AND ?",month.beginning_of_month, month.end_of_month)
|
||||
|
||||
# adding domains items
|
||||
registrar_activities.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]).each do |activity|
|
||||
price = load_price(activity)
|
||||
|
||||
if price.duration.include?('year')
|
||||
price.duration.to_i.times do |i|
|
||||
year = i+1
|
||||
hash = {
|
||||
"ProductID" => DOMAIN_TO_PRODUCT[price.zone_name],
|
||||
"Unit" => "tk",
|
||||
"ProductName" => ".#{price.zone_name} registreerimine: #{price.duration.to_i} aasta#{price.duration.to_i > 1 ? 't' : ''}",
|
||||
"UnitPriceWoVAT" => price.price.amount / price.duration.to_i
|
||||
}
|
||||
hash["StartDate"] = (activity.created_at + (year-1).year).end_of_month.strftime(date_format) if year > 1
|
||||
hash["EndDate"] = (activity.created_at + (year-1).year + 1).end_of_month.strftime(date_format) if year > 1
|
||||
|
||||
if items.has_key?(hash)
|
||||
items[hash]["Quantity"] += 1
|
||||
else
|
||||
items[hash] = { "RN" => counter.next, "RR" => counter.now - i, "Quantity" => 1 }
|
||||
end
|
||||
end
|
||||
else
|
||||
1.times do |i|
|
||||
quantity = price.account_activities
|
||||
.where(account_id: registrar.account_ids)
|
||||
.where(created_at: month.beginning_of_month..month.end_of_month)
|
||||
.where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW])
|
||||
.count
|
||||
|
||||
hash = {
|
||||
"ProductID" => DOMAIN_TO_PRODUCT[price.zone_name],
|
||||
"Unit" => "tk",
|
||||
"ProductName" => ".#{price.zone_name} registreerimine: #{price.duration.to_i} kuud",
|
||||
"UnitPriceWoVAT" => price.price.amount,
|
||||
}
|
||||
|
||||
if items.has_key?(hash)
|
||||
#items[hash]["Quantity"] += 1
|
||||
else
|
||||
items[hash] = { "RN" => counter.next, "RR" => counter.now - i, "Quantity" => quantity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
#adding prepaiments
|
||||
if items.any?
|
||||
total = 0
|
||||
items.each{ |key, val| total += val["Quantity"] * key["UnitPriceWoVAT"] }
|
||||
hash = {"ProductID" => Setting.directo_receipt_product_name, "Unit" => "tk", "ProductName" => "Domeenide ettemaks", "UnitPriceWoVAT"=>total}
|
||||
items[hash] = {"RN"=>counter.next, "RR" => counter.now, "Quantity"=> -1}
|
||||
end
|
||||
|
||||
# generating XML
|
||||
if items.any?
|
||||
directo_next += 1
|
||||
invoice_counter.next
|
||||
|
||||
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
||||
xml.invoices{
|
||||
xml.invoice("Number" =>directo_next,
|
||||
"InvoiceDate" =>invoices_until.strftime(date_format),
|
||||
"PaymentTerm" =>Setting.directo_receipt_payment_term,
|
||||
"CustomerCode"=>registrar.accounting_customer_code,
|
||||
"Language" =>"",
|
||||
"Currency" =>registrar_activities.first.currency,
|
||||
"SalesAgent" =>Setting.directo_sales_agent){
|
||||
xml.line("RN" => 1, "RR"=>1, "ProductName"=> "Domeenide registreerimine - #{I18n.l(invoices_until, format: "%B %Y").titleize}")
|
||||
items.each do |line, val|
|
||||
xml.line(val.merge(line))
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
data = builder.to_xml.gsub("\n",'')
|
||||
Rails.logger.info("[Directo] XML request: #{data}")
|
||||
|
||||
if debug
|
||||
STDOUT << "#{Time.zone.now.utc} - Directo xml had to be sent #{data}\n"
|
||||
else
|
||||
response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false)
|
||||
Rails.logger.info("[Directo] Directo responded with code: #{response.code}, body: #{response.body}")
|
||||
response = response.to_s
|
||||
|
||||
Setting.directo_monthly_number_last = directo_next
|
||||
Nokogiri::XML(response).css("Result").each do |res|
|
||||
Directo.create!(request: data, response: res.as_json.to_h, invoice_number: directo_next)
|
||||
Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
|
||||
end
|
||||
end
|
||||
else
|
||||
Rails.logger.info("[DIRECTO] Registrar #{registrar.id} has nothing to be sent to Directo")
|
||||
end
|
||||
|
||||
end
|
||||
STDOUT << "#{Time.zone.now.utc} - Directo invoices sending finished. #{invoice_counter.now} are sent\n"
|
||||
end
|
||||
|
||||
def self.load_price(account_activity)
|
||||
@pricelists ||= {}
|
||||
return @pricelists[account_activity.price_id] if @pricelists.has_key?(account_activity.price_id)
|
||||
@pricelists[account_activity.price_id] = account_activity.price
|
||||
end
|
||||
end
|
||||
|
|
|
@ -102,6 +102,22 @@ class Invoice < ApplicationRecord
|
|||
generator.generate
|
||||
end
|
||||
|
||||
def as_directo_json
|
||||
inv = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self))
|
||||
inv['customer_code'] = buyer.accounting_customer_code
|
||||
inv['issue_date'] = issue_date.strftime('%Y-%m-%d')
|
||||
inv['transaction_date'] = account_activity.bank_transaction&.paid_at&.strftime('%Y-%m-%d')
|
||||
inv['language'] = buyer.language
|
||||
inv['invoice_lines'] = [{
|
||||
'product_id': Setting.directo_receipt_product_name,
|
||||
'description': order,
|
||||
'quantity': 1,
|
||||
'price': ActionController::Base.helpers.number_with_precision(subtotal, precision: 2, separator: ".")
|
||||
}].as_json
|
||||
|
||||
inv
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def apply_default_buyer_vat_no
|
||||
|
@ -111,4 +127,4 @@ class Invoice < ApplicationRecord
|
|||
def calculate_total
|
||||
self.total = subtotal + vat_amount
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class Registrar < ApplicationRecord
|
||||
include Versions # version/registrar_version.rb
|
||||
include BookKeeping
|
||||
|
||||
has_many :domains, dependent: :restrict_with_error
|
||||
has_many :contacts, dependent: :restrict_with_error
|
||||
|
|
20
test/jobs/directo_invoice_forward_job_test.rb
Normal file
20
test/jobs/directo_invoice_forward_job_test.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
require "test_helper"
|
||||
|
||||
class DirectoInvoiceForwardJobTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@invoice = invoices(:one)
|
||||
end
|
||||
|
||||
def test_xml_is_include_transaction_date
|
||||
@invoice.update(total: @invoice.account_activity.bank_transaction.sum)
|
||||
@invoice.account_activity.bank_transaction.update(paid_at: Time.zone.now)
|
||||
|
||||
stub_request(:post, ENV['directo_invoice_url']).with do |request|
|
||||
request.body.include? 'TransactionDate'
|
||||
end
|
||||
|
||||
assert_nothing_raised do
|
||||
DirectoInvoiceForwardJob.run(monthly: false)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,20 +1,4 @@
|
|||
require 'test_helper'
|
||||
|
||||
class DirectoTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@invoice = invoices(:one)
|
||||
end
|
||||
|
||||
def test_xml_is_include_transaction_date
|
||||
@invoice.update(total: @invoice.account_activity.bank_transaction.sum)
|
||||
@invoice.account_activity.bank_transaction.update(paid_at: Time.zone.now)
|
||||
|
||||
stub_request(:post, ENV['directo_invoice_url']).with do |request|
|
||||
request.body.include? 'TransactionDate'
|
||||
end
|
||||
|
||||
assert_nothing_raised do
|
||||
Directo.send_receipts
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue