Merge pull request #2266 from internetee/eis_billing-request-to-generate-invoice

added api service for generate invoice in billing system
This commit is contained in:
Timo Võhmar 2022-06-02 14:42:36 +03:00 committed by GitHub
commit b909bf3408
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 1355 additions and 238 deletions

2
.gitignore vendored
View file

@ -11,6 +11,6 @@
/config/deploy.rb
/config/master.key
/.idea
/config/master.key
# Do not commit one. Instead, download the latest from https://github.com/internetee/style-guide.
.rubocop.yml

View file

@ -104,3 +104,6 @@ gem 'pghero'
gem 'pg_query', '>= 0.9.0'
gem 'newrelic_rpm'
gem 'newrelic-infinite_tracing'
# token
gem 'jwt'

View file

@ -275,6 +275,7 @@ GEM
activesupport (>= 4.2)
aes_key_wrap
bindata
jwt (2.3.0)
kaminari (1.2.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.2.1)
@ -560,6 +561,7 @@ DEPENDENCIES
iso8601 (= 0.13.0)
jquery-rails
jquery-ui-rails (= 6.0.1)
jwt
kaminari
lhv!
mime-types-data

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -13,6 +13,7 @@ module Admin
if @invoice&.persisted?
flash[:notice] = t(:record_created)
# send_invoice_data_to_billing_system
redirect_to [:admin, @invoice]
else
flash.now[:alert] = t(:failed_to_create_record)
@ -48,6 +49,8 @@ module Admin
def cancel
@invoice.cancel
EisBilling::SendInvoiceStatus.send_info(invoice_number: @invoice.number, status: 'cancelled')
redirect_to [:admin, @invoice], notice: t('.cancelled')
end

View file

@ -0,0 +1,59 @@
module EisBilling
class BaseController < ApplicationController
protect_from_forgery with: :null_session
skip_authorization_check # Temporary solution
# skip_before_action :verify_authenticity_token # Temporary solution
before_action :persistent
before_action :authorized
INITIATOR = 'billing'.freeze
def encode_token(payload)
JWT.encode(payload, ENV['secret_word'])
end
def auth_header
# { Authorization: 'Bearer <token>' }
request.headers['Authorization']
end
def decoded_token
return unless auth_header
token = auth_header.split(' ')[1]
begin
JWT.decode(token, billing_secret_key, true, algorithm: 'HS256')
rescue JWT::DecodeError
nil
end
end
def accessable_service
return decoded_token[0]['initiator'] == INITIATOR if decoded_token
false
end
def logged_in?
!!accessable_service
end
def authorized
render json: { message: 'Access denied' }, status: :unauthorized unless logged_in?
end
def billing_secret_key
ENV['billing_secret']
end
def logger
Rails.logger
end
def persistent
return true if Feature.billing_system_integrated?
render json: { message: "We don't work yet!" }, status: :unauthorized
end
end
end

View file

@ -0,0 +1,36 @@
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: :ok, json: { messege: 'Should return new directo number' }
end
private
def process_directo_response(xml, req)
Rails.logger.info "[Directo] - Responded with body: #{xml}"
Nokogiri::XML(req).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

View file

@ -0,0 +1,15 @@
class EisBilling::EInvoiceResponseController < EisBilling::BaseController
def update
invoice_number = params[:invoice_number]
mark_e_invoice_sent_at(invoice_number)
render status: :ok, json: { message: 'Response received' }
end
private
def mark_e_invoice_sent_at(invoice_number)
invoice = Invoice.find_by(number: invoice_number)
invoice.update(e_invoice_sent_at: Time.zone.now)
end
end

View file

@ -0,0 +1,48 @@
module EisBilling
class LhvConnectTransactionsController < EisBilling::BaseController
def create
params['_json'].each do |incoming_transaction|
process_transactions(incoming_transaction)
end
render status: :ok, json: { message: 'RECEIVED', params: params }
end
private
def process_transactions(incoming_transaction)
logger.info 'Got incoming transactions'
logger.info incoming_transaction
bank_statement = BankStatement.new(bank_code: Setting.registry_bank_code,
iban: Setting.registry_iban)
bank_statement_transaction(bank_statement: bank_statement, incoming_transaction: incoming_transaction)
end
def bank_statement_transaction(bank_statement:, incoming_transaction:)
ActiveRecord::Base.transaction do
bank_statement.save!
transaction = create_transaction(incoming_transaction: incoming_transaction, bank_statement: bank_statement)
next if transaction.registrar.blank?
create_invoice_if_missing(transaction) unless transaction.non_canceled?
end
end
def create_invoice_if_missing(transaction)
Invoice.create_from_transaction!(transaction) unless transaction.autobindable?
transaction.autobind_invoice
end
def create_transaction(incoming_transaction:, bank_statement:)
transaction_attributes = { sum: incoming_transaction['amount'],
currency: incoming_transaction['currency'],
paid_at: incoming_transaction['date'],
reference_no: incoming_transaction['payment_reference_number'],
description: incoming_transaction['payment_description'] }
bank_statement.bank_transactions.create!(transaction_attributes)
end
end
end

View file

@ -0,0 +1,54 @@
module EisBilling
class PaymentStatusController < EisBilling::BaseController
TYPE = 'PaymentOrders::EveryPay'.freeze
def update
payment_status = define_payment_status(params[:payment_state])
invoice = Invoice.find_by(number: params[:order_reference])
bank = create_bank_transfer(invoice: invoice, sum: params[:standing_amount], paid_at: params[:transaction_time])
create_payment_order(invoice: invoice, everypay_response: params, payment_status: payment_status)
registrar = invoice.buyer
bank.create_activity(registrar, invoice)
respond_to do |format|
format.json do
render status: :ok, content_type: 'application/json', layout: false, json: { message: 'ok' }
end
end
end
private
def define_payment_status(status)
return :paid if PaymentOrders::EveryPay::SUCCESSFUL_PAYMENT.include? status
:failed
end
def create_payment_order(invoice:, everypay_response:, payment_status:)
payment = PaymentOrder.new
payment.type = TYPE
payment.invoice = invoice
payment.response = everypay_response
payment.status = payment_status
payment.save
payment
end
def create_bank_transfer(invoice:, sum:, paid_at:)
bank = BankTransaction.new
bank.description = invoice.order
bank.reference_no = invoice.reference_no
bank.currency = invoice.currency
bank.iban = invoice.seller_iban
bank.sum = sum
bank.paid_at = paid_at
bank.buyer_name = invoice.buyer_name
bank.save
bank
end
end
end

View file

@ -17,6 +17,8 @@ class Registrar
def cancel
@invoice.cancel
EisBilling::SendInvoiceStatus.send_info(invoice_number: @invoice.number, status: 'cancelled')
redirect_to [:registrar, @invoice], notice: t('.cancelled')
end

View file

@ -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

View file

@ -0,0 +1,84 @@
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 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

View file

@ -0,0 +1,44 @@
class SendEInvoiceTwoJob < ApplicationJob
discard_on HTTPClient::TimeoutError
def perform(invoice_id, payable: true)
logger.info "Started to process e-invoice for invoice_id #{invoice_id}"
invoice = Invoice.find_by(id: invoice_id)
return unless need_to_process_invoice?(invoice: invoice, payable: payable)
send_invoice_to_eis_billing(invoice: invoice, payable: payable)
invoice.update(e_invoice_sent_at: Time.zone.now)
rescue StandardError => e
log_error(invoice: invoice, error: e)
raise e
end
private
def need_to_process_invoice?(invoice:, payable:)
logger.info "Checking if need to process e-invoice #{invoice}, payable: #{payable}"
return false if invoice.blank?
return false if invoice.do_not_send_e_invoice? && payable
true
end
def send_invoice_to_eis_billing(invoice:, payable:)
result = EisBilling::SendEInvoice.send_request(invoice: invoice, payable: payable)
logger.info result.body
end
def log_error(invoice:, error:)
id = invoice.try(:id) || invoice
message = <<~TEXT.squish
There was an error sending e-invoice for invoice with ID # #{id}.
The error message was the following: #{error}
This job will retry.
TEXT
logger.error message
end
def logger
Rails.logger
end
end

View file

@ -4,8 +4,13 @@ module Billing
MULTI_REGEXP = /(\d{2,20})/
def self.generate
base = Base.generate
"#{base}#{base.check_digit}"
if Feature.billing_system_integrated?
result = EisBilling::GetReferenceNumber.send_request
JSON.parse(result.body)['reference_number']
else
base = Base.generate
"#{base}#{base.check_digit}"
end
end
def self.valid?(ref)

View file

@ -1,13 +1,7 @@
class Feature
# def self.obj_and_extensions_statuses_enabled?
# return false if ENV['obj_and_extensions_prohibited'] == 'false'
#
# ENV['obj_and_extensions_prohibited'] || false
# end
#
# def self.enable_lock_domain_with_new_statuses?
# return false if ENV['enable_lock_domain_with_new_statuses'] == 'false'
#
# ENV['enable_lock_domain_with_new_statuses'] || false
# end
def self.billing_system_integrated?
return false if ENV['billing_system_integrated'] == 'false'
ENV['billing_system_integrated'] || false
end
end

View file

@ -40,8 +40,38 @@ class Invoice < ApplicationRecord
attribute :vat_rate, ::Type::VatRate.new
def set_invoice_number
last_no = Invoice.order(number: :desc).limit(1).pick(:number)
def validate_invoice_number(result)
response = JSON.parse(result.body)
billing_restrictions_issue if response['code'] == '403'
billing_out_of_range_issue if response['error'] == 'out of range'
end
def billing_restrictions_issue
errors.add(:base, I18n.t('cannot get access'))
logger.error('PROBLEM WITH TOKEN')
throw(:abort)
end
def billing_out_of_range_issue
errors.add(:base, I18n.t('failed_to_generate_invoice_invoice_number_limit_reached'))
logger.error('INVOICE NUMBER LIMIT REACHED, COULD NOT GENERATE INVOICE')
throw(:abort)
end
def invoice_number_from_billing
result = EisBilling::GetInvoiceNumber.send_invoice
validate_invoice_number(result)
self.number = JSON.parse(result.body)['invoice_number'].to_i
end
def generate_invoice_number_legacy
last_no = Invoice.all
.where(number: Setting.invoice_number_min.to_i...Setting.invoice_number_max.to_i)
.order(number: :desc)
.limit(1)
.pick(:number)
if last_no && last_no >= Setting.invoice_number_min.to_i
self.number = last_no + 1
@ -51,9 +81,15 @@ class Invoice < ApplicationRecord
return if number <= Setting.invoice_number_max.to_i
errors.add(:base, I18n.t('failed_to_generate_invoice_invoice_number_limit_reached'))
logger.error('INVOICE NUMBER LIMIT REACHED, COULD NOT GENERATE INVOICE')
throw(:abort)
billing_out_of_range_issue
end
def set_invoice_number
if Feature.billing_system_integrated?
invoice_number_from_billing
else
generate_invoice_number_legacy
end
end
def to_s

View file

@ -107,7 +107,20 @@ class Registrar < ApplicationRecord
.deliver_later(wait: 1.minute)
end
SendEInvoiceJob.set(wait: 1.minute).perform_now(invoice.id, payable: payable)
if Feature.billing_system_integrated?
add_invoice_instance = EisBilling::AddDeposits.new(invoice)
result = add_invoice_instance.send_invoice
link = JSON.parse(result.body)['everypay_link']
invoice.update(payment_link: link)
end
if Feature.billing_system_integrated?
SendEInvoiceTwoJob.set(wait: 1.minute).perform_now(invoice.id, payable: payable)
else
SendEInvoiceJob.set(wait: 1.minute).perform_now(invoice.id, payable: payable)
end
invoice
end

View file

@ -0,0 +1,37 @@
module EisBilling
class AddDeposits < EisBilling::Base
attr_reader :invoice
def initialize(invoice)
@invoice = invoice
end
def send_invoice
send_request(json_obj: parse_invoice)
end
private
def parse_invoice
data = {}
data[:transaction_amount] = invoice.total.to_s
data[:order_reference] = invoice.number
data[:customer_name] = invoice.buyer_name
data[:customer_email] = invoice.buyer_email
data[:custom_field1] = invoice.description
data[:custom_field2] = INITIATOR
data[:invoice_number] = invoice.number
data
end
def send_request(json_obj:)
http = EisBilling::Base.base_request(url: invoice_generator_url)
http.post(invoice_generator_url, json_obj.to_json, EisBilling::Base.headers)
end
def invoice_generator_url
"#{BASE_URL}/api/v1/invoice_generator/invoice_generator"
end
end
end

View file

@ -0,0 +1,35 @@
module EisBilling
class Base
BASE_URL = ENV['eis_billing_system_base_url'] || 'https://st-billing.infra.tld.ee'
INITIATOR = 'registry'.freeze
def self.base_request(url:)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true unless Rails.env.development?
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if Rails.env.development?
http
end
def self.generate_token
JWT.encode(payload, billing_secret)
end
def self.payload
{ initiator: INITIATOR }
end
def self.headers
{
'Authorization' => "Bearer #{generate_token}",
'Content-Type' => 'application/json',
}
end
def self.billing_secret
ENV['billing_secret']
end
end
end

View file

@ -0,0 +1,16 @@
module EisBilling
class GetInvoiceNumber < EisBilling::Base
def self.send_invoice
send_request
end
def self.send_request
http = EisBilling::Base.base_request(url: invoice_number_generator_url)
http.post(invoice_number_generator_url, nil, EisBilling::Base.headers)
end
def self.invoice_number_generator_url
"#{BASE_URL}/api/v1/invoice_generator/invoice_number_generator"
end
end
end

View file

@ -0,0 +1,22 @@
module EisBilling
class GetReferenceNumber < EisBilling::Base
def self.send_request
send_it
end
def self.obj_data
{
initiator: INITIATOR,
}
end
def self.send_it
http = EisBilling::Base.base_request(url: reference_number_generator_url)
http.post(reference_number_generator_url, obj_data.to_json, EisBilling::Base.headers)
end
def self.reference_number_generator_url
"#{EisBilling::Base::BASE_URL}/api/v1/invoice_generator/reference_number_generator"
end
end
end

View file

@ -0,0 +1,23 @@
module EisBilling
class SendDataToDirecto < EisBilling::Base
def self.send_request(object_data:, monthly:, dry:)
send_info(object_data: object_data, monthly: monthly, dry: dry)
end
def self.send_info(object_data:, monthly:, dry:)
prepared_data = {
invoice_data: object_data,
monthly: monthly,
dry: dry,
initiator: INITIATOR,
}
http = EisBilling::Base.base_request(url: directo_url)
http.post(directo_url, prepared_data.to_json, EisBilling::Base.headers)
end
def self.directo_url
"#{BASE_URL}/api/v1/directo/directo"
end
end
end

View file

@ -0,0 +1,52 @@
module EisBilling
class SendEInvoice < EisBilling::Base
def self.send_request(invoice:, payable:)
send_info(invoice: invoice, payable: payable)
end
def self.send_info(invoice:, payable:)
items = []
prepared_data = prepare_data(invoice: invoice, payable: payable)
invoice.items.each do |invoice_item|
items << prepare_item(invoice_item)
end
prepared_data[:items] = items
http = EisBilling::Base.base_request(url: e_invoice_url)
http.post(e_invoice_url, prepared_data.to_json, EisBilling::Base.headers)
end
def self.prepare_item(invoice_item)
{
description: invoice_item.description,
price: invoice_item.price,
quantity: invoice_item.quantity,
unit: invoice_item.unit,
subtotal: invoice_item.subtotal,
vat_rate: invoice_item.vat_rate,
vat_amount: invoice_item.vat_amount,
total: invoice_item.total,
}
end
def self.prepare_data(invoice:, payable:)
{
invoice: invoice,
vat_amount: invoice.vat_amount,
invoice_subtotal: invoice.subtotal,
buyer_billing_email: invoice.buyer.billing_email,
buyer_e_invoice_iban: invoice.buyer.e_invoice_iban,
seller_country_code: invoice.seller_country_code,
buyer_country_code: invoice.buyer_country_code,
payable: payable,
initiator: EisBilling::Base::INITIATOR,
}
end
def self.e_invoice_url
"#{BASE_URL}/api/v1/e_invoice/e_invoice"
end
end
end

View file

@ -0,0 +1,21 @@
module EisBilling
class SendInvoiceStatus < EisBilling::Base
def self.send_info(invoice_number:, status:)
send_request(invoice_number: invoice_number, status: status)
end
def self.send_request(invoice_number:, status:)
json_obj = {
invoice_number: invoice_number,
status: status,
}
http = EisBilling::Base.base_request(url: invoice_status_url)
http.post(invoice_status_url, json_obj.to_json, EisBilling::Base.headers)
end
def self.invoice_status_url
"#{BASE_URL}/api/v1/invoice_generator/invoice_status"
end
end
end

View file

@ -0,0 +1,2 @@
<h1>EisBilling::DirectoResponse#update</h1>
<p>Find me in app/views/eis_billing/directo_response/update.html.erb</p>

View file

@ -0,0 +1,2 @@
<h1>EisBilling::EInvoiceResponse#update</h1>
<p>Find me in app/views/eis_billing/e_invoice_response/update.html.erb</p>

View file

View file

@ -1,7 +1,8 @@
%h4= t('registrar.invoices.pay_invoice')
%hr
- locals[:payment_channels].each do |meth|
- meth = meth.strip
= link_to registrar_payment_with_path(meth, invoice_id: params[:id]), id: meth do
= image_tag("#{meth}.png")
- if @invoice.payment_link.present?
= link_to @invoice.payment_link, target: :_blank do
= image_tag("everypay.png", class: 'everypay', style: "width: 100px; height: 20px;")
- else
= "No everypay link"

View file

@ -235,3 +235,11 @@ registry_demo_accredited_users_url: 'http://registry.test/api/v1/accreditation_c
a_and_aaaa_validation_timeout: '1'
nameserver_validation_timeout: '1'
eis_billing_system_base_url: 'http://eis_billing_system:3000'
billing_secret: acd50ed44524d24c826d724fda922b790ca4130b02d62bcc8f85f1b863195ba8d155c4346037364eb59135d1e9dcba6cd8a4046ee4aef3c3a0878fcdf8e85efd
billing_system_integrated: 'true'
secret_access_word: 'please-Give-Me-accesS'
secret_word: 'this-secret-should-be-change'
allow_accr_endspoints: 'true'

View file

@ -0,0 +1 @@
bXY8qqnyzpMtyIDA74p4C1GiW+cLO7yeUXl5nwZB7yy1Lkv0XbF8juV07MCm7mBgh0BfjK9Ey2sx+QiXH/PimvhNDtgy6vSNbgb5AcQBJ6XwHlXei/DNF7Bt+r5V+ixrDU6FJZ8Y9EQyjZC9zcPiAaMhDMmA71bfiE2vO2TT1T6BZcjD5P4GKmYM7pMDgKATrwauzd6ejuYfTpSBHR51zuUEEBL1uZKSXW/i6vNAE+yuRxNOULWISA0zDPaCipnrMwjf8yWkp9L4qLIcggYpepZm6t+OyAD2XMTz/5skfQRtZ0PGDs7gzJLdAYD6ErUTU9N+n6SPhPpWu0zPFMR/A9t6AudgupmLeADGnkzUyRa4jCLzOnklV4rzAT1vM4zdVhGCgd3JXQL6zptrgHgRQN8i3BhBY2w3KXtFV1N61M6cMuuvTHMMFVI+V9sbRJ58Nok9EVbu5U/WRpuJElKq7xo1bgtY/0NOFq2K+TqZT6RBtSH5sWIdUGJJIbI6VngzfZpUNPiyg9eyShK2Wa2v1BlyLK3zYRD8F9/kNUvLCX7vgSjI/pwifokVAF51GhykhlmpfOyLmEEc011DwD+F4xjkYN1xHY8=--YBWnRjhG+BqNrfar--RcZCpjUq+MNhMOydjZWWTA==

View file

@ -11,6 +11,13 @@ Rails.application.routes.draw do
mount PgHero::Engine, at: "pghero"
end
namespace :eis_billing do
put '/payment_status', to: 'payment_status#update', as: 'payment_status', :format => false, :defaults => { :format => 'json' }
put '/directo_response', to: 'directo_response#update', as: 'directo_response'
put '/e_invoice_response', to: 'e_invoice_response#update', as: 'e_invoice_response'
post '/lhv_connect_transactions', to: 'lhv_connect_transactions#create', as: 'lhv_connect_transactions'
end
namespace :epp do
constraints(EppConstraint.new(:session)) do
get 'session/hello', to: 'sessions#hello', as: 'hello'

View file

@ -0,0 +1,5 @@
class AddPaymentLinkToInvoice < ActiveRecord::Migration[6.1]
def change
add_column :invoices, :payment_link, :string
end
end

View file

@ -5411,6 +5411,5 @@ INSERT INTO "schema_migrations" (version) VALUES
('20220413073315'),
('20220413084536'),
('20220413084748'),
('20220504090512');
('20220504090512'),
('20220406085500');

View file

@ -0,0 +1,85 @@
BASE_URL = ENV['eis_billing_system_base_url'] || 'https://st-billing.infra.tld.ee'
INITIATOR = 'registry'.freeze
namespace :eis_billing do
desc 'One time task to export invoice data to billing system'
task export_invoices: :environment do
parsed_data = []
status = 'unpaid'
Invoice.all.each do |invoice|
if invoice.cancelled?
status = 'cancelled'
else
status = invoice.paid? ? 'paid' : 'unpaid'
end
transaction_time = invoice.receipt_date if invoice.paid?
parsed_data << {
invoice_number: invoice.number,
initiator: 'registry',
transaction_amount: invoice.total,
status: status,
in_directo: invoice.in_directo,
e_invoice_sent_at: invoice.e_invoice_sent_at,
transaction_time: transaction_time
}
end
base_request(url: import_invoice_data_url, json_obj: parsed_data)
end
desc 'One time task to export reference number of registrars to billing system'
task export_references: :environment do
parsed_data = []
Registrar.all.each do |registrar|
parsed_data << {
reference_number: registrar.reference_no,
initiator: 'registry',
registrar_name: registrar.name
}
end
base_request(url: import_reference_data_url, json_obj: parsed_data)
end
end
def import_reference_data_url
"#{BASE_URL}/api/v1/import_data/reference_data"
end
def import_invoice_data_url
"#{BASE_URL}/api/v1/import_data/invoice_data"
end
def base_request(url:, json_obj:)
uri = URI(url)
http = Net::HTTP.new(uri.host, uri.port)
unless Rails.env.development?
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http.post(url, json_obj.to_json, headers)
end
def generate_token
JWT.encode(payload, billing_secret)
end
def payload
{ initiator: INITIATOR }
end
def headers
{
'Authorization' => "Bearer #{generate_token}",
'Content-Type' => 'application/json',
}
end
def self.billing_secret
ENV['billing_secret']
end

View file

@ -17,7 +17,7 @@ namespace :registrars do
next if reload_pending || !threshold_reached
Registrar.transaction do
registrar.issue_prepayment_invoice(reload_amount)
registrar.issue_prepayment_invoice(reload_amount, 'reload balance')
registrar.settings['balance_auto_reload']['pending'] = true
registrar.save!
end

View file

@ -24,14 +24,30 @@ class AdminAreaInvoicesIntegrationTest < ApplicationIntegrationTest
end
def test_create_new_invoice
visit new_admin_invoice_path
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
assert_text 'Create new invoice'
select 'Best Names', from: 'deposit_registrar_id', match: :first
fill_in 'Amount', with: '1000'
click_on 'Save'
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_equal page.status_code, 200
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
visit new_admin_invoice_path
assert_text 'Create new invoice'
select 'Best Names', from: 'deposit_registrar_id', match: :first
fill_in 'Amount', with: '1000'
click_on 'Save'
assert_equal page.status_code, 200
end
end
def test_visit_list_of_invoices_pages

View file

@ -0,0 +1,43 @@
require 'test_helper'
class DirectoResponseTest < ApplicationIntegrationTest
setup do
sign_in users(:api_bestnames)
@invoice = invoices(:one)
@response_xml = "<?xml version='1.0' encoding='UTF-8'?><results><Result Type='0' Desc='OK' docid='#{@invoice.number}' doctype='ARVE' submit='Invoices'/></results>"
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_should_created_directo_instance
if Feature.billing_system_integrated?
directo_response_from_billing = {
response: @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
end
def test_should_update_related_invoice
if Feature.billing_system_integrated?
directo_response_from_billing = {
response: @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
end

View file

@ -0,0 +1,17 @@
require 'test_helper'
class EInvoiceResponseTest < ApplicationIntegrationTest
setup do
sign_in users(:api_bestnames)
@invoice = invoices(:one)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_invoice_should_be_mark_as_sent
assert_nil @invoice.e_invoice_sent_at
put eis_billing_e_invoice_response_path, params: { invoice_number: @invoice.number}
@invoice.reload
assert_not_nil @invoice.e_invoice_sent_at
end
end

View file

@ -0,0 +1,43 @@
require 'test_helper'
class LhvConnectTransactionsIntegrationTest < ApplicationIntegrationTest
setup do
@invoice = invoices(:unpaid)
sign_in users(:api_bestnames)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_should_saved_transaction_data
if Feature.billing_system_integrated?
test_transaction_1 = OpenStruct.new(amount: 0.1,
currency: 'EUR',
date: Time.zone.today,
payment_reference_number: '2199812',
payment_description: "description 2199812")
test_transaction_2 = OpenStruct.new(amount: 0.1,
currency: 'EUR',
date: Time.zone.today,
payment_reference_number: '2199813',
payment_description: "description 2199813")
test_transaction_3 = OpenStruct.new(amount: 0.1,
currency: 'EUR',
date: Time.zone.today,
payment_reference_number: '2199814',
payment_description: "description 2199814")
lhv_transactions = []
lhv_transactions << test_transaction_1
lhv_transactions << test_transaction_2
lhv_transactions << test_transaction_3
assert_difference 'BankStatement.count', 3 do
assert_difference 'BankTransaction.count', 3 do
post eis_billing_lhv_connect_transactions_path, params: { "_json" => JSON.parse(lhv_transactions.to_json) },
headers: { 'HTTP_COOKIE' => 'session=api_bestnames' }
end
end
end
end
end

View file

@ -16,72 +16,87 @@ class BankTransactionTest < ActiveSupport::TestCase
end
def test_binds_if_this_sum_invoice_already_present
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
another_invoice.update(reference_no: '7654321', number: '2221')
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
another_invoice.update(reference_no: '7654321', number: '2221')
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item.save
another_invoice.reload
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item.save
another_invoice.reload
first_transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
first_transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
first_transaction.create_activity(another_invoice.buyer, another_invoice)
first_transaction.create_activity(another_invoice.buyer, another_invoice)
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
end
end
end
def test_binds_if_this_sum_cancelled_invoice_already_present
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item.save
another_invoice.reload
another_invoice.update(reference_no: '1234567', number: '2221', cancelled_at: Time.zone.now)
another_item.save
another_invoice.reload
another_invoice.update(reference_no: '1234567', number: '2221', cancelled_at: Time.zone.now)
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
end
end
end
def test_marks_the_first_one_as_paid_if_same_sum
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
another_invoice.update(reference_no: '7654321', number: '2221')
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
create_payable_invoice(number: '2222', total: 10, reference_no: '1234567')
another_invoice = @invoice.dup
another_invoice.save(validate: false)
another_invoice.update(reference_no: '7654321', number: '2221')
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item.save
another_invoice.reload
another_item = @invoice.items.first.dup
another_item.invoice = another_invoice
another_item.save
another_invoice.reload
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
transaction = BankTransaction.new(sum: 10,
description: 'Order nr 1 from registrar 1234567 second number 2345678')
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
assert_difference 'AccountActivity.count' do
transaction.autobind_invoice
end
@invoice.reload
another_invoice.reload
assert(@invoice.paid?)
assert_not(another_invoice.paid?)
end
@invoice.reload
another_invoice.reload
assert(@invoice.paid?)
assert_not(another_invoice.paid?)
end
def test_matches_against_invoice_nubmber_and_reference_number_in_description

View file

@ -7,7 +7,12 @@ class ReferenceNoTest < ActiveSupport::TestCase
end
def test_generated_reference_number_conforms_to_format
reference_no = Billing::ReferenceNo.generate
assert_match Billing::ReferenceNo::REGEXP, reference_no
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/reference_number_generator")
.to_return(status: 200, body: "{\"reference_number\":\"12332\"}", headers: {})
reference_no = Billing::ReferenceNo.generate
assert_match Billing::ReferenceNo::REGEXP, reference_no
end
end
end

View file

@ -5,6 +5,7 @@ class InvoiceTest < ActiveSupport::TestCase
setup do
@invoice = invoices(:one)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_fixture_is_valid
@ -79,6 +80,10 @@ class InvoiceTest < ActiveSupport::TestCase
end
def test_buyer_vat_no_is_taken_from_registrar_by_default
invoice_n = Invoice.order(number: :desc).last.number
response = OpenStruct.new(body: "{\"invoice_number\":\"#{invoice_n + 3}\"}")
Spy.on(EisBilling::GetInvoiceNumber, :send_invoice).and_return(response)
registrar = registrars(:bestnames)
registrar.vat_no = 'US1234'
invoice = @invoice.dup
@ -113,31 +118,69 @@ class InvoiceTest < ActiveSupport::TestCase
end
def test_creates_invoice_with_bank_transaction_total
registrar = registrars(:bestnames)
transaction = bank_transactions(:one).dup
transaction.reference_no = registrar.reference_no
transaction.sum = 250
if Feature.billing_system_integrated?
registrar = registrars(:bestnames)
transaction = bank_transactions(:one).dup
transaction.reference_no = registrar.reference_no
transaction.sum = 250
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 250, invoice.total
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator")
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
transaction.sum = 146.88
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 146.88, invoice.total
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator")
.to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
transaction.sum = 0.99
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 0.99, invoice.total
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 250, invoice.total
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 4}\"}", headers: {})
transaction.sum = 146.88
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 146.88, invoice.total
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 5}\"}", headers: {})
transaction.sum = 0.99
invoice = Invoice.create_from_transaction!(transaction)
assert_equal 0.99, invoice.total
end
end
def test_emails_invoice_after_creating_topup_invoice
registrar = registrars(:bestnames)
transaction = bank_transactions(:one).dup
transaction.reference_no = registrar.reference_no
transaction.sum = 250
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_emails 1 do
Invoice.create_from_transaction!(transaction)
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
registrar = registrars(:bestnames)
transaction = bank_transactions(:one).dup
transaction.reference_no = registrar.reference_no
transaction.sum = 250
response = OpenStruct.new(body: "{\"invoice_number\":\"#{invoice_n + 3}\"}")
Spy.on(EisBilling::GetInvoiceNumber, :send_invoice).and_return(response)
assert_emails 1 do
Invoice.create_from_transaction!(transaction)
end
end
end
end

View file

@ -6,6 +6,7 @@ class RegistrarTest < ActiveJob::TestCase
@original_default_language = Setting.default_language
@original_days_to_keep_invoices_active = Setting.days_to_keep_invoices_active
@old_validation_type = Truemail.configure.default_validation_type
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
teardown do
@ -144,23 +145,55 @@ class RegistrarTest < ActiveJob::TestCase
end
def test_issues_new_invoice
travel_to Time.zone.parse('2010-07-05')
Setting.days_to_keep_invoices_active = 10
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
invoice = @registrar.issue_prepayment_invoice(100)
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
assert_equal Date.parse('2010-07-05'), invoice.issue_date
assert_equal Date.parse('2010-07-15'), invoice.due_date
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
travel_to Time.zone.parse('2010-07-05')
Setting.days_to_keep_invoices_active = 10
invoice = @registrar.issue_prepayment_invoice(100)
assert_equal Date.parse('2010-07-05'), invoice.issue_date
assert_equal Date.parse('2010-07-15'), invoice.due_date
end
end
def test_issues_e_invoice_along_with_invoice
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
end
EInvoice::Providers::TestProvider.deliveries.clear
perform_enqueued_jobs do
@registrar.issue_prepayment_invoice(100)
end
assert_equal 1, EInvoice::Providers::TestProvider.deliveries.count
unless Feature.billing_system_integrated?
assert_equal 1, EInvoice::Providers::TestProvider.deliveries.count
end
end
def test_invalid_without_address_street

View file

@ -0,0 +1,15 @@
require 'test_helper'
class SendDataToDirectoTest < ActiveSupport::TestCase
setup do
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_should_send_data_to_billing_directo
stub_request(:post, "https://eis_billing_system:3000/api/v1/directo/directo").
to_return(status: 200, body: "ok", headers: {})
res = EisBilling::SendDataToDirecto.send_request(object_data: [], monthly: true, dry: true)
assert_equal res.body, "ok"
end
end

View file

@ -6,6 +6,7 @@ class AdminAreaBankStatementTest < ApplicationSystemTestCase
travel_to Time.zone.parse('2010-07-05 00:30:00')
@invoice = invoices(:one)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_update_bank_statement
@ -54,24 +55,39 @@ class AdminAreaBankStatementTest < ApplicationSystemTestCase
end
def test_can_bind_statement_transactions
registrar = registrars(:bestnames)
registrar.issue_prepayment_invoice(500)
invoice = registrar.invoices.last
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator")
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
registrar = registrars(:bestnames)
create_bank_statement
click_link_or_button 'Add'
assert_text 'Create bank transaction'
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator")
.to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
fill_in 'Description', with: "Invoice with id #{invoice.number}"
fill_in 'Reference number', with: invoice.reference_no
fill_in 'Sum', with: invoice.total
fill_in 'Paid at', with: Time.zone.today.to_s
click_link_or_button 'Save'
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response")
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
click_link_or_button 'Back to bank statement'
click_link_or_button 'Bind invoices'
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice")
.to_return(status: 200, body: "", headers: {})
assert_text 'Invoices were fully binded'
registrar.issue_prepayment_invoice(500)
invoice = registrar.invoices.last
create_bank_statement
click_link_or_button 'Add'
assert_text 'Create bank transaction'
fill_in 'Description', with: "Invoice with id #{invoice.number}"
fill_in 'Reference number', with: invoice.reference_no
fill_in 'Sum', with: invoice.total
fill_in 'Paid at', with: Time.zone.today.to_s
click_link_or_button 'Save'
click_link_or_button 'Back to bank statement'
click_link_or_button 'Bind invoices'
assert_text 'Invoices were fully binded'
end
end
def create_bank_statement

View file

@ -11,6 +11,7 @@ class AdminAreaInvoicesTest < ApplicationSystemTestCase
end
def test_cancels_an_invoice
Spy.on(EisBilling::SendInvoiceStatus, :send_info).and_return(true)
@invoice.account_activity = nil
assert @invoice.cancellable?

View file

@ -14,25 +14,30 @@ class AdminRegistrarsSystemTest < ApplicationSystemTestCase
end
def test_creates_new_registrar
assert_nil Registrar.find_by(name: 'Acme Ltd')
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/reference_number_generator").
to_return(status: 200, body: "{\"reference_number\":\"12332\"}", headers: {})
visit admin_registrars_path
click_on 'New registrar'
assert_nil Registrar.find_by(name: 'Acme Ltd')
fill_in 'Name', with: 'Acme Ltd'
fill_in 'Reg no', with: '1234'
fill_in 'Contact e-mail', with: 'any@acme.test'
fill_in 'Street', with: 'any'
fill_in 'City', with: 'any'
fill_in 'State / Province', with: 'any'
fill_in 'Zip', with: 'any'
select 'United States', from: 'Country'
fill_in 'Accounting customer code', with: 'test'
fill_in 'Code', with: 'test'
click_on 'Create registrar'
visit admin_registrars_path
click_on 'New registrar'
assert_text 'Registrar has been successfully created'
assert_text 'Acme Ltd'
fill_in 'Name', with: 'Acme Ltd'
fill_in 'Reg no', with: '1234'
fill_in 'Contact e-mail', with: 'any@acme.test'
fill_in 'Street', with: 'any'
fill_in 'City', with: 'any'
fill_in 'State / Province', with: 'any'
fill_in 'Zip', with: 'any'
select 'United States', from: 'Country'
fill_in 'Accounting customer code', with: 'test'
fill_in 'Code', with: 'test'
click_on 'Create registrar'
assert_text 'Registrar has been successfully created'
assert_text 'Acme Ltd'
end
end
def test_updates_registrar

View file

@ -0,0 +1,12 @@
require 'application_system_test_case'
class AddDepositsTest < ApplicationSystemTestCase
include ActionMailer::TestHelper
setup do
sign_in users(:api_bestnames)
@invoice = invoices(:one)
ActionMailer::Base.deliveries.clear
end
end

View file

@ -4,6 +4,10 @@ class BalanceTopUpTest < ApplicationSystemTestCase
setup do
sign_in users(:api_bestnames)
@original_registry_vat_rate = Setting.registry_vat_prc
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
teardown do
@ -11,20 +15,32 @@ class BalanceTopUpTest < ApplicationSystemTestCase
end
def test_creates_new_invoice
Setting.registry_vat_prc = 0.1
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
visit registrar_invoices_url
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '25.5'
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response")
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
assert_difference 'Invoice.count' do
click_link_or_button 'Add'
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice")
.to_return(status: 200, body: "", headers: {})
Setting.registry_vat_prc = 0.1
visit registrar_invoices_url
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '25.5'
assert_difference 'Invoice.count' do
click_link_or_button 'Add'
end
invoice = Invoice.last
assert_equal BigDecimal(10), invoice.vat_rate
assert_equal BigDecimal('28.05'), invoice.total
assert_text 'Please pay the following invoice'
end
invoice = Invoice.last
assert_equal BigDecimal(10), invoice.vat_rate
assert_equal BigDecimal('28.05'), invoice.total
assert_text 'Please pay the following invoice'
end
end

View file

@ -3,6 +3,8 @@ require 'application_system_test_case'
class NewInvoicePaymentTest < ApplicationSystemTestCase
def setup
super
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
@original_vat_prc = Setting.registry_vat_prc
Setting.registry_vat_prc = 0.2
@ -23,26 +25,4 @@ class NewInvoicePaymentTest < ApplicationSystemTestCase
fill_in 'Description', with: 'My first invoice'
click_link_or_button 'Add'
end
def test_create_new_SEB_payment
create_invoice_and_visit_its_page
click_link_or_button 'seb'
form = page.find('form')
assert_equal('https://www.seb.ee/cgi-bin/dv.sh/ipank.r', form['action'])
assert_equal('post', form['method'])
assert_equal('240.00', form.find_by_id('VK_AMOUNT', visible: false).value)
end
def test_create_new_Every_Pay_payment
create_invoice_and_visit_its_page
click_link_or_button 'every_pay'
expected_hmac_fields = 'account_id,amount,api_username,callback_url,' +
'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type'
form = page.find('form')
assert_equal('https://igw-demo.every-pay.com/transactions/', form['action'])
assert_equal('post', form['method'])
assert_equal(expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value)
assert_equal('240.00', form.find_by_id('amount', visible: false).value)
end
end

View file

@ -6,6 +6,9 @@ class NewInvoiceTest < ApplicationSystemTestCase
@user = users(:api_bestnames)
sign_in @user
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
end
def test_show_balance
@ -14,35 +17,59 @@ class NewInvoiceTest < ApplicationSystemTestCase
end
def test_create_new_invoice_with_positive_amount
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200.00'
fill_in 'Description', with: 'My first invoice'
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200.00'
fill_in 'Description', with: 'My first invoice'
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
end
assert_text 'Please pay the following invoice'
assert_text "Invoice no. #{invoice_n + 3}"
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
assert_text 'Please pay the following invoice'
assert_text 'Invoice no. 131050'
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
def test_create_new_invoice_with_comma_in_number
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200,00'
fill_in 'Description', with: 'My first invoice'
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
visit registrar_invoices_path
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '200,00'
fill_in 'Description', with: 'My first invoice'
assert_difference 'Invoice.count', 1 do
click_link_or_button 'Add'
end
assert_text 'Please pay the following invoice'
assert_text "Invoice no. #{invoice_n + 3}"
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
assert_text 'Please pay the following invoice'
assert_text 'Invoice no. 131050'
assert_text 'Subtotal 200,00 €'
assert_text 'Pay invoice'
end
def test_create_new_invoice_fails_when_amount_is_0

View file

@ -8,9 +8,13 @@ class RegistrarAreaInvoicesTest < ApplicationSystemTestCase
@invoice = invoices(:one)
ActionMailer::Base.deliveries.clear
eis_response = OpenStruct.new(body: "{\"payment_link\":\"http://link.test\"}")
Spy.on_instance_method(EisBilling::AddDeposits, :send_invoice).and_return(eis_response)
end
def test_cancels_an_invoice
Spy.on(EisBilling::SendInvoiceStatus, :send_info).and_return(true)
@invoice.account_activity = nil
assert @invoice.cancellable?
@ -40,4 +44,18 @@ class RegistrarAreaInvoicesTest < ApplicationSystemTestCase
assert_current_path registrar_invoice_path(@invoice)
assert_text 'Invoice has been sent'
end
end
def test_if_invoice_unpaid_and_not_generated_link_comes_then_should_render_no_everypay_link
invoice = invoices(:unpaid)
visit registrar_invoice_url(invoice)
assert_text 'No everypay link'
end
def test_if_invoice_aldready_paid_there_should_not_any_everypay_link
visit registrar_invoice_url(@invoice)
assert_no_text 'No everypay link'
assert_no_text 'Everypay link'
end
end

View file

@ -77,15 +77,33 @@ class ProcessPaymentsTaskTest < ActiveJob::TestCase
end
def test_if_invoice_is_overdue_than_48_hours
assert_not @invoice.paid?
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
@account_activity.update(activity_type: "add_credit", bank_transaction: nil, created_at: Time.zone.today - 3.days, creator_str: 'AdminUser')
@invoice.update(account_activity: @account_activity, total: @payment_amount)
assert @invoice.paid?
Spy.on_instance_method(SendEInvoiceTwoJob, :perform_now).and_return(true)
assert_difference 'AccountActivity.count' do
assert_difference 'Invoice.count' do
capture_io { run_task }
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_not @invoice.paid?
@account_activity.update(activity_type: "add_credit", bank_transaction: nil, created_at: Time.zone.today - 3.days, creator_str: 'AdminUser')
@invoice.update(account_activity: @account_activity, total: @payment_amount)
assert @invoice.paid?
assert_difference 'AccountActivity.count' do
assert_difference 'Invoice.count' do
capture_io { run_task }
end
end
end
end
@ -143,15 +161,32 @@ class ProcessPaymentsTaskTest < ActiveJob::TestCase
assert payment_order.failed?
end
def test_credits_registrar_account_without_invoice_beforehand
registrar = registrars(:bestnames)
def test_credits_registrar_athout_invoice_beforehand
if Feature.billing_system_integrated?
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}")
assert_changes -> { registrar.accounts.first.balance } do
run_task
end
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_changes -> { registrar.invoices.count } do
run_task
Spy.on_instance_method(SendEInvoiceTwoJob, :perform_now).and_return(true)
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
registrar = registrars(:bestnames)
assert_changes -> { registrar.accounts.first.balance } do
run_task
end
assert_changes -> { registrar.invoices.count } do
run_task
end
end
end
@ -163,25 +198,40 @@ class ProcessPaymentsTaskTest < ActiveJob::TestCase
end
def test_topup_creates_invoice_and_send_it_as_paid
registrar = registrars(:bestnames)
@invoice.payment_orders.destroy_all
@invoice.destroy
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
perform_enqueued_jobs do
run_task
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
registrar = registrars(:bestnames)
@invoice.payment_orders.destroy_all
@invoice.destroy
perform_enqueued_jobs do
run_task
end
invoice = Invoice.last
assert invoice.paid?
assert_not invoice.e_invoice_sent_at.blank?
pdf_source = Invoice::PdfGenerator.new(invoice)
pdf_source.send(:invoice_html).include?('Receipt date')
email= ActionMailer::Base.deliveries.last
assert email.subject.include?('already paid')
assert_equal 0.1, registrar.invoices.last.total
end
invoice = Invoice.last
assert invoice.paid?
assert_not invoice.e_invoice_sent_at.blank?
pdf_source = Invoice::PdfGenerator.new(invoice)
pdf_source.send(:invoice_html).include?('Receipt date')
email= ActionMailer::Base.deliveries.last
assert email.subject.include?('already paid')
assert_equal 0.1, registrar.invoices.last.total
end
def test_output

View file

@ -5,6 +5,7 @@ class ReloadBalanceTaskTest < ActiveSupport::TestCase
setup do
@registrar = registrars(:bestnames)
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
end
def test_issues_invoice_when_auto_reload_is_enabled_and_threshold_reached
@ -20,15 +21,30 @@ class ReloadBalanceTaskTest < ActiveSupport::TestCase
end
def test_issues_invoice_when_auto_reload_is_enabled_and_threshold_reached
reload_amount = 100
registrar = registrar_with_auto_reload_enabled_and_threshold_reached(reload_amount)
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_difference -> { registrar.invoices.count } do
capture_io { run_task }
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
reload_amount = 100
registrar = registrar_with_auto_reload_enabled_and_threshold_reached(reload_amount)
assert_difference -> { registrar.invoices.count } do
capture_io { run_task }
end
invoice = registrar.invoices.last
assert_equal Time.zone.today, invoice.e_invoice_sent_at.to_date
end
invoice = registrar.invoices.last
assert_equal Time.zone.today, invoice.e_invoice_sent_at.to_date
end
def test_skips_issuing_invoice_when_threshold_is_not_reached
@ -50,21 +66,51 @@ class ReloadBalanceTaskTest < ActiveSupport::TestCase
end
def test_marks_registrar_as_pending_balance_reload
registrar = registrar_with_auto_reload_enabled_and_threshold_reached
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
capture_io { run_task }
registrar.reload
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
assert registrar.settings['balance_auto_reload']['pending']
registrar = registrar_with_auto_reload_enabled_and_threshold_reached
capture_io { run_task }
registrar.reload
assert registrar.settings['balance_auto_reload']['pending']
end
end
def test_output
reload_amount = 100
registrar = registrar_with_auto_reload_enabled_and_threshold_reached(reload_amount)
assert_equal 'Best Names', registrar.name
if Feature.billing_system_integrated?
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
to_return(status: 200, body: "{\"everypay_link\":\"http://link.test\"}", headers: {})
assert_output %(Registrar "Best Names" got #{number_to_currency(reload_amount, unit: 'EUR')}\nInvoiced total: 1\n) do
run_task
invoice_n = Invoice.order(number: :desc).last.number
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}", headers: {})
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 3}\"}, {\"date\":\"#{Time.zone.now-10.minutes}\"}", headers: {})
stub_request(:post, "https://eis_billing_system:3000/api/v1/e_invoice/e_invoice").
to_return(status: 200, body: "", headers: {})
reload_amount = 100
registrar = registrar_with_auto_reload_enabled_and_threshold_reached(reload_amount)
assert_equal 'Best Names', registrar.name
assert_output %(Registrar "Best Names" got #{number_to_currency(reload_amount, unit: 'EUR')}\nInvoiced total: 1\n) do
run_task
end
end
end