From 0259dd7fec604117e3756bd036bbe2f820200ea9 Mon Sep 17 00:00:00 2001 From: olegphenomenon Date: Tue, 1 Feb 2022 13:35:11 +0200 Subject: [PATCH] added directo handler for interaction with billing system --- .../directo_response_controller.rb | 35 ++++ .../eis_billing/payment_status_controller.rb | 2 +- app/jobs/directo_invoice_forward_job.rb | 2 + app/jobs/directo_invoice_forward_two_job.rb | 175 ++++++++++++++++++ .../eis_billing/send_data_to_directo.rb | 30 +++ .../directo_response/update.html.erb | 2 + config/routes.rb | 1 + .../eis_billing/directo_response_test.rb | 40 ++++ 8 files changed, 286 insertions(+), 1 deletion(-) create mode 100644 app/controllers/eis_billing/directo_response_controller.rb create mode 100644 app/jobs/directo_invoice_forward_two_job.rb create mode 100644 app/services/eis_billing/send_data_to_directo.rb create mode 100644 app/views/eis_billing/directo_response/update.html.erb create mode 100644 test/integration/eis_billing/directo_response_test.rb diff --git a/app/controllers/eis_billing/directo_response_controller.rb b/app/controllers/eis_billing/directo_response_controller.rb new file mode 100644 index 000000000..3009f5c09 --- /dev/null +++ b/app/controllers/eis_billing/directo_response_controller.rb @@ -0,0 +1,35 @@ +class EisBilling::DirectoResponseController < EisBilling::BaseController + def update + response = params[:response] + xml_data = params[:xml_data] + @month = params.fetch(:month, false) + + process_directo_response(xml_data, response) + render status: 200, json: { messege: 'Should return new directo number', status: :ok } + end + + private + + def process_directo_response(xml, req) + Rails.logger.info "[Directo] - Responded with body: #{xml}" + Nokogiri::XML(xml).css('Result').each do |res| + if @month + mark_invoice_as_sent(res: res, req: req) + else + inv = Invoice.find_by(number: res.attributes['docid'].value.to_i) + mark_invoice_as_sent(invoice: inv, res: res, req: req) + end + end + end + + def mark_invoice_as_sent(invoice: nil, res:, req:) + directo_record = Directo.new(response: res.as_json.to_h, + request: req, invoice_number: res.attributes['docid'].value.to_i) + if invoice + directo_record.item = invoice + invoice.update(in_directo: true) + end + + directo_record.save! + end +end diff --git a/app/controllers/eis_billing/payment_status_controller.rb b/app/controllers/eis_billing/payment_status_controller.rb index 6f16dcb2d..9147ecf76 100644 --- a/app/controllers/eis_billing/payment_status_controller.rb +++ b/app/controllers/eis_billing/payment_status_controller.rb @@ -8,7 +8,7 @@ module EisBilling sum = params[:standing_amount] everypay_response = params - payment_status = define_payment_status(params[:payment_state]) + payment_status = define_payment_status(params[:payment_state]) invoice = Invoice.find_by(number: invoice_number) diff --git a/app/jobs/directo_invoice_forward_job.rb b/app/jobs/directo_invoice_forward_job.rb index 43a537ade..04da1a424 100644 --- a/app/jobs/directo_invoice_forward_job.rb +++ b/app/jobs/directo_invoice_forward_job.rb @@ -21,6 +21,7 @@ class DirectoInvoiceForwardJob < ApplicationJob 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 @@ -69,6 +70,7 @@ class DirectoInvoiceForwardJob < ApplicationJob def sync_with_directo assign_monthly_numbers if @month + Rails.logger.info("[Directo] - attempting to send following XML:\n #{@client.invoices.as_xml}") return if @dry diff --git a/app/jobs/directo_invoice_forward_two_job.rb b/app/jobs/directo_invoice_forward_two_job.rb new file mode 100644 index 000000000..0165e66a6 --- /dev/null +++ b/app/jobs/directo_invoice_forward_two_job.rb @@ -0,0 +1,175 @@ +class DirectoInvoiceForwardTwoJob < ApplicationJob + def perform(monthly: false, dry: false) + data = nil + + if monthly + @month = Time.zone.now - 1.month + data = collect_monthly_data + else + data = collect_receipts_data + end + + EisBilling::SendDataToDirecto.send_request(object_data: data, monthly: monthly, dry: dry) + end + + def collect_receipts_data + unsent_invoices = Invoice.where(in_directo: false).non_cancelled + collected_data = [] + + unsent_invoices.each do |invoice| + unless valid_invoice_conditions?(invoice) + Rails.logger.info "[DIRECTO] Invoice #{invoice.number} has been skipped" + next + end + collected_data << invoice.as_directo_json + end + + collected_data + 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 collect_monthly_data + registrars_data = [] + + Registrar.where.not(test_registrar: true).find_each do |registrar| + registrars_data << { + registrar: registrar, + registrar_summery: registrar.monthly_summary(month: @month) + } + end + + registrars_data + end + + # def perform(monthly: false, dry: false) + # @dry = dry + # (@month = Time.zone.now - 1.month) if monthly + + # @client = new_directo_client + # monthly ? send_monthly_invoices : send_receipts + # end + + # def new_directo_client + # DirectoApi::Client.new(ENV['directo_invoice_url'], Setting.directo_sales_agent, + # Setting.directo_receipt_payment_term) + # 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 + # Registrar.where.not(test_registrar: true).find_each do |registrar| + # next unless registrar.cash_account + + # @client = new_directo_client + # send_invoice_for_registrar(registrar) + # end + # end + + # def send_invoice_for_registrar(registrar) + # summary = registrar.monthly_summary(month: @month) + # @client.invoices.add_with_schema(invoice: summary, schema: 'summary') unless summary.nil? + + # sync_with_directo if @client.invoices.count.positive? + # end + + # def assign_monthly_numbers + # raise 'Directo Counter is going to be out of period!' if directo_counter_exceedable?(@client.invoices.count) + + # min_directo = Setting.directo_monthly_number_min.presence.try(:to_i) + # directo_number = [Setting.directo_monthly_number_last.presence.try(:to_i), + # min_directo].compact.max || 0 + + # @client.invoices.each do |inv| + # directo_number += 1 + # inv.number = directo_number + # end + # 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 + # assign_monthly_numbers if @month + # Rails.logger.info("[Directo] - attempting to send following XML:\n #{@client.invoices.as_xml}") + # return if @dry + + # res = @client.invoices.deliver(ssl_verify: false) + # process_directo_response(res.body, @client.invoices.as_xml) + # rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, + # EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError + # Rails.logger.info('[Directo] Failed to communicate via API') + # end + + # def process_directo_response(xml, req) + # Rails.logger.info "[Directo] - Responded with body: #{xml}" + # Nokogiri::XML(xml).css('Result').each do |res| + # if @month + # mark_invoice_as_sent(res: res, req: req) + # else + # inv = Invoice.find_by(number: res.attributes['docid'].value.to_i) + # mark_invoice_as_sent(invoice: inv, res: res, req: req) + # end + # end + # end + + def mark_invoice_as_sent(invoice: nil, res:, req:) + directo_record = Directo.new(response: res.as_json.to_h, + request: req, invoice_number: res.attributes['docid'].value.to_i) + if invoice + directo_record.item = invoice + invoice.update(in_directo: true) + else + update_directo_number(num: directo_record.invoice_number) + end + + directo_record.save! + end + + def update_directo_number(num:) + return unless num.to_i > Setting.directo_monthly_number_last.to_i + + Setting.directo_monthly_number_last = num.to_i + end + + def directo_counter_exceedable?(invoice_count) + 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 + + return true if max_directo && max_directo < (last_directo + invoice_count) + + false + end +end diff --git a/app/services/eis_billing/send_data_to_directo.rb b/app/services/eis_billing/send_data_to_directo.rb new file mode 100644 index 000000000..615925990 --- /dev/null +++ b/app/services/eis_billing/send_data_to_directo.rb @@ -0,0 +1,30 @@ +module EisBilling + class SendDataToDirecto < EisBilling::Base + def self.send_request(object_data:, monthly:, dry:) + base_request(object_data: object_data, monthly: monthly, dry: dry) + end + + def self.base_request(object_data:, monthly:, dry:) + prepared_data = { + invoice_data: object_data, + monthly: monthly, + dry: dry, + initiator: 'registry' + } + + uri = URI(invoice_generator_url) + http = Net::HTTP.new(uri.host, uri.port) + headers = { + 'Authorization' => 'Bearer foobar', + 'Content-Type' => 'application/json', + 'Accept' => TOKEN + } + + http.post(invoice_generator_url, prepared_data.to_json, headers) + end + + def self.invoice_generator_url + "#{BASE_URL}/api/v1/directo/directo" + end + end +end diff --git a/app/views/eis_billing/directo_response/update.html.erb b/app/views/eis_billing/directo_response/update.html.erb new file mode 100644 index 000000000..693715b2d --- /dev/null +++ b/app/views/eis_billing/directo_response/update.html.erb @@ -0,0 +1,2 @@ +

EisBilling::DirectoResponse#update

+

Find me in app/views/eis_billing/directo_response/update.html.erb

diff --git a/config/routes.rb b/config/routes.rb index 68be463f5..a91287b49 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -13,6 +13,7 @@ Rails.application.routes.draw do namespace :eis_billing do put '/payment_status', to: 'payment_status#update', as: 'payment_status' + put '/directo_response', to: 'directo_response#update', as: 'directo_response' post '/lhv_connect_transactions', to: 'lhv_connect_transactions#create', as: 'lhv_connect_transactions' end diff --git a/test/integration/eis_billing/directo_response_test.rb b/test/integration/eis_billing/directo_response_test.rb new file mode 100644 index 000000000..b1e7426cd --- /dev/null +++ b/test/integration/eis_billing/directo_response_test.rb @@ -0,0 +1,40 @@ +require 'test_helper' + +class DirectoResponseTest < ApplicationIntegrationTest + setup do + sign_in users(:api_bestnames) + + @invoice = invoices(:one) + @response_xml = '' + end + + def test_should_created_directo_instance + directo_response_from_billing = { + response: 'this is response', + xml_data: @response_xml, + month: true + } + + assert_difference 'Directo.count', 1 do + put eis_billing_directo_response_path, params: JSON.parse(directo_response_from_billing.to_json), + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + end + + def test_should_update_related_invoice + directo_response_from_billing = { + response: 'this is response', + xml_data: @response_xml + } + + refute @invoice.in_directo + + assert_difference 'Directo.count', 1 do + put eis_billing_directo_response_path, params: JSON.parse(directo_response_from_billing.to_json), + headers: { 'HTTP_COOKIE' => 'session=api_bestnames' } + end + + @invoice.reload + assert @invoice.in_directo + end +end