mirror of
https://github.com/internetee/registry.git
synced 2025-07-28 13:36:15 +02:00
Merge pull request #2531 from internetee/68-creating-syncronization-of-invoice-changes
creating sync with billing
This commit is contained in:
commit
da514f9a50
11 changed files with 715 additions and 60 deletions
40
app/controllers/eis_billing/invoices_controller.rb
Normal file
40
app/controllers/eis_billing/invoices_controller.rb
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
module EisBilling
|
||||||
|
class InvoicesController < BaseController
|
||||||
|
before_action :load_invoice, only: :update
|
||||||
|
|
||||||
|
def update
|
||||||
|
state = InvoiceStateMachine.new(invoice: @invoice, status: params[:status])
|
||||||
|
if @invoice.update(modified_params) && state.call
|
||||||
|
render json: {
|
||||||
|
message: 'Invoice data was successfully updated',
|
||||||
|
}, status: :ok
|
||||||
|
else
|
||||||
|
render json: {
|
||||||
|
error: {
|
||||||
|
message: @invoice.errors.full_messages
|
||||||
|
}
|
||||||
|
}, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def load_invoice
|
||||||
|
@invoice = Invoice.find_by(number: params[:invoice][:invoice_number])
|
||||||
|
return if @invoice.present?
|
||||||
|
|
||||||
|
render json: {
|
||||||
|
error: {
|
||||||
|
message: "Invoice with #{params[:invoice][:invoice_number]} number not found",
|
||||||
|
}
|
||||||
|
}, status: :not_found and return
|
||||||
|
end
|
||||||
|
|
||||||
|
def modified_params
|
||||||
|
{
|
||||||
|
in_directo: params[:invoice][:in_directo],
|
||||||
|
e_invoice_sent_at: params[:invoice][:sent_at_omniva],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,19 +3,20 @@ module EisBilling
|
||||||
TYPE = 'PaymentOrders::EveryPay'.freeze
|
TYPE = 'PaymentOrders::EveryPay'.freeze
|
||||||
|
|
||||||
def update
|
def update
|
||||||
payment_status = define_payment_status(params[:payment_state])
|
|
||||||
invoice = Invoice.find_by(number: params[:order_reference])
|
invoice = Invoice.find_by(number: params[:order_reference])
|
||||||
|
|
||||||
return if invoice.paid?
|
if invoice.paid?
|
||||||
|
render json: { message: 'Invoice already paid' }, status: :ok
|
||||||
|
else
|
||||||
|
invoice.process_payment(
|
||||||
|
payment_type: TYPE,
|
||||||
|
everypay_response: params,
|
||||||
|
payment_status: define_payment_status(params[:payment_state]),
|
||||||
|
sum: params[:standing_amount],
|
||||||
|
transaction_time: params[:transaction_time]
|
||||||
|
)
|
||||||
|
|
||||||
bank = create_bank_transfer(invoice: invoice, sum: params[:standing_amount], paid_at: params[:transaction_time])
|
render json: { message: 'Payment is proccessing' }, status: :ok
|
||||||
create_payment_order(invoice: invoice, everypay_response: params, payment_status: payment_status)
|
|
||||||
bank.bind_invoice(params[:order_reference])
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.json do
|
|
||||||
render status: :ok, content_type: 'application/json', layout: false, json: { message: 'ok' }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,30 +27,5 @@ module EisBilling
|
||||||
|
|
||||||
:failed
|
:failed
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -31,4 +31,22 @@ module Invoice::Cancellable
|
||||||
def not_cancelled?
|
def not_cancelled?
|
||||||
!cancelled?
|
!cancelled?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def cancel_manualy
|
||||||
|
account_activity = AccountActivity.find_by(invoice_id: id)
|
||||||
|
account_activity_dup = account_activity.dup
|
||||||
|
account_activity_dup.sum = -account_activity.sum.to_f
|
||||||
|
account_activity_dup.save
|
||||||
|
account_activity.update(invoice_id: nil)
|
||||||
|
account_activity_dup.update(invoice_id: nil)
|
||||||
|
mark_cancelled_payment_order
|
||||||
|
account_activity.save && account_activity_dup.save
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def mark_cancelled_payment_order
|
||||||
|
payment_order = payment_orders.last
|
||||||
|
payment_order.update(notes: 'Cancelled')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,4 +23,34 @@ module Invoice::Payable
|
||||||
def unpaid?
|
def unpaid?
|
||||||
!paid?
|
!paid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def process_payment(**options)
|
||||||
|
payment = options[:payment_type].constantize.new(invoice: self)
|
||||||
|
payment.response = options[:everypay_response]
|
||||||
|
payment.status = options[:payment_status]
|
||||||
|
payment.save!
|
||||||
|
|
||||||
|
bank_transaction = payment.base_transaction(sum: options[:sum],
|
||||||
|
paid_at: options[:transaction_time] || Time.zone.now,
|
||||||
|
buyer_name: buyer_name)
|
||||||
|
bank_transaction.bind_invoice(number)
|
||||||
|
end
|
||||||
|
|
||||||
|
def autobind_manually
|
||||||
|
return if paid?
|
||||||
|
|
||||||
|
bank_statement = BankStatement.new(
|
||||||
|
bank_code: Setting.registry_bank_code,
|
||||||
|
iban: Setting.registry_iban
|
||||||
|
)
|
||||||
|
bank_statement.bank_transactions.build(
|
||||||
|
description: description,
|
||||||
|
sum: total,
|
||||||
|
reference_no: reference_no,
|
||||||
|
paid_at: Time.zone.now.to_date,
|
||||||
|
currency: 'EUR'
|
||||||
|
)
|
||||||
|
bank_statement.save!
|
||||||
|
bank_statement.bind_invoices(manual: true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
53
app/models/invoice_state_machine.rb
Normal file
53
app/models/invoice_state_machine.rb
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
class InvoiceStateMachine
|
||||||
|
attr_reader :invoice, :status
|
||||||
|
|
||||||
|
def initialize(invoice:, status:)
|
||||||
|
@invoice = invoice
|
||||||
|
@status = status.to_sym
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
case status
|
||||||
|
when :paid
|
||||||
|
mark_as_paid
|
||||||
|
when :cancelled
|
||||||
|
mark_as_cancel
|
||||||
|
when :unpaid
|
||||||
|
mark_as_unpaid
|
||||||
|
else
|
||||||
|
push_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def mark_as_paid
|
||||||
|
return push_error unless invoice.payable?
|
||||||
|
return true if invoice.paid?
|
||||||
|
|
||||||
|
invoice.autobind_manually
|
||||||
|
invoice
|
||||||
|
end
|
||||||
|
|
||||||
|
def mark_as_cancel
|
||||||
|
return push_error unless invoice.cancellable?
|
||||||
|
return true if invoice.cancelled?
|
||||||
|
|
||||||
|
invoice.cancel
|
||||||
|
invoice
|
||||||
|
end
|
||||||
|
|
||||||
|
def mark_as_unpaid
|
||||||
|
return push_error if invoice.paid? && invoice.payment_orders&.last&.payment_reference? || invoice.cancelled?
|
||||||
|
return true unless invoice.paid?
|
||||||
|
|
||||||
|
invoice.cancel_manualy
|
||||||
|
invoice
|
||||||
|
end
|
||||||
|
|
||||||
|
def push_error
|
||||||
|
invoice.errors.add(:base, "Inavalid state #{status}")
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
|
@ -64,6 +64,10 @@ class PaymentOrder < ApplicationRecord
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def payment_reference?
|
||||||
|
response && response['payment_reference'].present?
|
||||||
|
end
|
||||||
|
|
||||||
def base_transaction(sum:, paid_at:, buyer_name:)
|
def base_transaction(sum:, paid_at:, buyer_name:)
|
||||||
BankTransaction.new(
|
BankTransaction.new(
|
||||||
description: invoice.order,
|
description: invoice.order,
|
||||||
|
|
|
@ -16,6 +16,7 @@ Rails.application.routes.draw do
|
||||||
put '/directo_response', to: 'directo_response#update', as: 'directo_response'
|
put '/directo_response', to: 'directo_response#update', as: 'directo_response'
|
||||||
put '/e_invoice_response', to: 'e_invoice_response#update', as: 'e_invoice_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'
|
post '/lhv_connect_transactions', to: 'lhv_connect_transactions#create', as: 'lhv_connect_transactions'
|
||||||
|
resource :invoices, only: [:update]
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace :epp do
|
namespace :epp do
|
||||||
|
|
316
test/integration/eis_billing/invoices_test.rb
Normal file
316
test/integration/eis_billing/invoices_test.rb
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class StubAuthorization < ApplicationController
|
||||||
|
skip_authorization_check
|
||||||
|
|
||||||
|
def authorized
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
EisBilling::BaseController = StubAuthorization
|
||||||
|
|
||||||
|
class EInvoiceResponseTest < ApplicationIntegrationTest
|
||||||
|
setup do
|
||||||
|
sign_in users(:api_bestnames)
|
||||||
|
@invoice = invoices(:one)
|
||||||
|
|
||||||
|
response_message = {
|
||||||
|
message: 'got it'
|
||||||
|
}
|
||||||
|
stub_request(:post, 'https://eis_billing_system:3000/api/v1/invoice_generator/invoice_status')
|
||||||
|
.to_return(status: 200, body: response_message.to_json, headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should update status of invoice if payment order is existed' do
|
||||||
|
@invoice.update(total: 120.0)
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: @invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
@invoice.account_activity.delete && @invoice.reload
|
||||||
|
|
||||||
|
assert_equal @invoice.payment_orders.pluck(:status), %w[issued issued]
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
@invoice.reload
|
||||||
|
@invoice.payment_orders.each(&:reload)
|
||||||
|
|
||||||
|
invoice = Invoice.find(@invoice.id)
|
||||||
|
assert_equal invoice.payment_orders.pluck(:status), %w[issued issued paid]
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should update invoice data as directo and omniva' do
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: @invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 270.0,
|
||||||
|
status: 'unpaid',
|
||||||
|
in_directo: true,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'unpaid'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_equal @invoice.payment_orders.pluck(:status), %w[issued issued]
|
||||||
|
assert_nil @invoice.e_invoice_sent_at
|
||||||
|
refute @invoice.in_directo
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
|
||||||
|
@invoice.payment_orders.each(&:reload)
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
assert_equal @invoice.payment_orders.pluck(:status), %w[issued issued]
|
||||||
|
assert @invoice.in_directo
|
||||||
|
assert_not_nil @invoice.e_invoice_sent_at
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should create new payment order if payment order and activity are missing, but status has paid status' do
|
||||||
|
invoice = invoices(:one)
|
||||||
|
|
||||||
|
invoice.payment_orders.destroy_all and invoice.account_activity.destroy
|
||||||
|
invoice.update(total: 120.0)
|
||||||
|
invoice.reload
|
||||||
|
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert invoice.payment_orders.empty?
|
||||||
|
assert_nil invoice.account_activity
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
|
||||||
|
invoice.reload
|
||||||
|
invoice.payment_orders.each(&:reload)
|
||||||
|
|
||||||
|
assert_equal invoice.payment_orders.count, 1
|
||||||
|
assert invoice.payment_orders.first.paid?
|
||||||
|
assert invoice.account_activity
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should ignore payment order creation if payment status is not paid and payment order not existed' do
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: @invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 270.0,
|
||||||
|
status: 'cancelled',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'cancelled'
|
||||||
|
}
|
||||||
|
|
||||||
|
@invoice.payment_orders.destroy_all and @invoice.account_activity.destroy
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
assert @invoice.payment_orders.empty?
|
||||||
|
assert_nil @invoice.account_activity
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params and @invoice.reload
|
||||||
|
|
||||||
|
assert @invoice.payment_orders.empty?
|
||||||
|
assert_nil @invoice.account_activity
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should add balance if payment order mark as paid' do
|
||||||
|
invoice = invoices(:one)
|
||||||
|
item = invoice.items.first
|
||||||
|
|
||||||
|
invoice.payment_orders.destroy_all and invoice.account_activity.destroy
|
||||||
|
invoice.update(total: 120.0) && invoice.reload
|
||||||
|
item.update(price: 100.0) && item.reload
|
||||||
|
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert invoice.payment_orders.empty?
|
||||||
|
assert_nil invoice.account_activity
|
||||||
|
|
||||||
|
account = invoice.buyer.accounts.first
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
|
||||||
|
invoice.reload
|
||||||
|
invoice.payment_orders.each(&:reload)
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
assert_equal invoice.payment_orders.count, 1
|
||||||
|
assert invoice.payment_orders.first.paid?
|
||||||
|
assert invoice.account_activity
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 200.0
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'should change nothing if invoice is already paid' do
|
||||||
|
assert @invoice.account_activity.present?
|
||||||
|
assert @invoice.payment_orders.present?
|
||||||
|
|
||||||
|
account = @invoice.buyer.accounts.first
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
assert @invoice.paid?
|
||||||
|
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: @invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: @invoice.total,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should decrease balance and again add if user change paid invoice to cancel and then again to paid' do
|
||||||
|
invoice = invoices(:one)
|
||||||
|
item = invoice.items.first
|
||||||
|
|
||||||
|
invoice.payment_orders.destroy_all and invoice.account_activity.destroy
|
||||||
|
invoice.update(total: 120.0) && invoice.reload
|
||||||
|
item.update(price: 100.0) && item.reload
|
||||||
|
|
||||||
|
add_balance_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
assert invoice.payment_orders.empty?
|
||||||
|
assert_nil invoice.account_activity
|
||||||
|
|
||||||
|
account = invoice.buyer.accounts.first
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: add_balance_params
|
||||||
|
|
||||||
|
invoice.reload
|
||||||
|
invoice.payment_orders.each(&:reload)
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
assert_equal invoice.payment_orders.count, 1
|
||||||
|
assert invoice.payment_orders.first.paid?
|
||||||
|
assert invoice.account_activity
|
||||||
|
assert invoice.paid?
|
||||||
|
assert_equal account.balance.to_f, 200.0
|
||||||
|
|
||||||
|
decrease_balance_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: invoice.number,
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'unpaid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'unpaid'
|
||||||
|
}
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: decrease_balance_params
|
||||||
|
invoice.reload
|
||||||
|
invoice.payment_orders.each(&:reload)
|
||||||
|
account.reload
|
||||||
|
assert invoice.unpaid?
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'it should return an error if invoice not existing' do
|
||||||
|
incoming_params = {
|
||||||
|
invoice: {
|
||||||
|
invoice_number: 'nonexisted-invoice',
|
||||||
|
initiator: 'registry',
|
||||||
|
payment_reference: '93b29d54ae08f7728e72ee3fe0e88855cd1d266912039d7d23fa2b54b7e1b349',
|
||||||
|
transaction_amount: 120.0,
|
||||||
|
status: 'paid',
|
||||||
|
in_directo: false,
|
||||||
|
everypay_response: {
|
||||||
|
'some' => 'some'
|
||||||
|
},
|
||||||
|
sent_at_omniva: Time.zone.now - 10.minutes
|
||||||
|
},
|
||||||
|
status: 'paid'
|
||||||
|
}
|
||||||
|
|
||||||
|
put eis_billing_invoices_path, params: incoming_params
|
||||||
|
registry_response = JSON.parse(response.body).with_indifferent_access[:error]
|
||||||
|
|
||||||
|
assert_equal registry_response[:message], 'Invoice with nonexisted-invoice number not found'
|
||||||
|
end
|
||||||
|
end
|
|
@ -9,10 +9,7 @@ class PaymentStatusTest < ApplicationIntegrationTest
|
||||||
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
|
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def shoudl_update_buyer_balance
|
test 'should mark an invoice as paid' do
|
||||||
assert @invoice.paid?
|
|
||||||
assert_equal @invoice.buyer.balance.to_f, 100.0
|
|
||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
payment_state: 'settled',
|
payment_state: 'settled',
|
||||||
order_reference: @unpaid.number,
|
order_reference: @unpaid.number,
|
||||||
|
@ -20,13 +17,57 @@ class PaymentStatusTest < ApplicationIntegrationTest
|
||||||
transaction_time: Time.zone.now,
|
transaction_time: Time.zone.now,
|
||||||
}
|
}
|
||||||
|
|
||||||
put eis_billing_payment_status_path, params: payload
|
item = @unpaid.items.first
|
||||||
|
|
||||||
@invoice.reload
|
refute @unpaid.paid?
|
||||||
@invoice.buyer.reload
|
assert_equal @unpaid.buyer.balance.to_f, 100.0
|
||||||
@registrar.reload
|
assert_equal item.price, 5.0
|
||||||
|
|
||||||
|
put eis_billing_payment_status_path, params: payload
|
||||||
|
@unpaid.reload
|
||||||
|
assert_equal @unpaid.buyer.balance.to_f, 105.0
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'ignore additonal callbacks if invoice is already paid' do
|
||||||
|
payload = {
|
||||||
|
payment_state: 'settled',
|
||||||
|
order_reference: @unpaid.number,
|
||||||
|
standing_amount: @unpaid.total,
|
||||||
|
transaction_time: Time.zone.now,
|
||||||
|
}
|
||||||
|
|
||||||
|
item = @unpaid.items.first
|
||||||
|
|
||||||
|
refute @unpaid.paid?
|
||||||
|
assert_equal @unpaid.buyer.balance.to_f, 100.0
|
||||||
|
assert_equal item.price, 5.0
|
||||||
|
|
||||||
|
put eis_billing_payment_status_path, params: payload
|
||||||
|
@unpaid.reload
|
||||||
|
assert_equal @unpaid.buyer.balance.to_f, 105.0
|
||||||
|
assert @unpaid.paid?
|
||||||
|
|
||||||
|
put eis_billing_payment_status_path, params: payload
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert_equal @unpaid.buyer.balance.to_f, 105.0
|
||||||
|
assert @unpaid.paid?
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'send callback to already paid invoice' do
|
||||||
|
payload = {
|
||||||
|
payment_state: 'settled',
|
||||||
|
order_reference: @invoice.number,
|
||||||
|
standing_amount: @invoice.total,
|
||||||
|
transaction_time: Time.zone.now,
|
||||||
|
}
|
||||||
|
|
||||||
assert @invoice.paid?
|
assert @invoice.paid?
|
||||||
assert_equal @invoice.buyer.balance.to_f, 100.0
|
assert_equal @invoice.buyer.balance.to_f, 100.0
|
||||||
|
|
||||||
|
put eis_billing_payment_status_path, params: payload
|
||||||
|
@invoice.reload
|
||||||
|
assert_equal @invoice.buyer.balance.to_f, 100.0
|
||||||
|
assert @invoice.paid?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
105
test/models/invoice_state_machinte_test.rb
Normal file
105
test/models/invoice_state_machinte_test.rb
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class InvoiceTest < ActiveSupport::TestCase
|
||||||
|
include ActionMailer::TestHelper
|
||||||
|
|
||||||
|
setup do
|
||||||
|
@invoice = invoices(:one)
|
||||||
|
@unpaid = invoices(:unpaid)
|
||||||
|
|
||||||
|
stub_request(:post, 'https://eis_billing_system:3000/api/v1/invoice_generator/invoice_status')
|
||||||
|
.with(
|
||||||
|
body: '{"invoice_number":2,"status":"paid"}'
|
||||||
|
)
|
||||||
|
.to_return(status: 200, body: '', headers: {})
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_unpaid_invoice_can_be_change_status_to_paid
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'paid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.paid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_no_any_errors_if_invoice_with_unpaid_status_set_again_unpaid
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'unpaid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
assert @unpaid.errors.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_only_unpaid_invoice_can_be_cancelled
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'cancelled').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.cancelled?
|
||||||
|
|
||||||
|
assert @invoice.paid?
|
||||||
|
InvoiceStateMachine.new(invoice: @invoice, status: 'cancelled').call
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
assert_equal @invoice.errors.full_messages.join, 'Inavalid state cancelled'
|
||||||
|
assert @invoice.errors.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cancelled_invoiced_cannot_be_unpaid
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'cancelled').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.cancelled?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'unpaid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.cancelled?
|
||||||
|
|
||||||
|
assert @unpaid.errors.present?
|
||||||
|
assert_equal @unpaid.errors.full_messages.join, 'Inavalid state unpaid'
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_if_paid_invoice_not_have_response_from_everypay_it_can_be_unpaid_back
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'paid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.paid?
|
||||||
|
assert_nil @unpaid.payment_orders.last.payment_reference?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'unpaid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_if_paid_invoice_has_response_from_everypay_it_cannot_be_rollback
|
||||||
|
assert !@unpaid.paid?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'paid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.paid?
|
||||||
|
payment_order = @unpaid.payment_orders.last
|
||||||
|
payment_order.response = {}
|
||||||
|
payment_order.response[:payment_reference] = 'responsefromeveryapy'
|
||||||
|
payment_order.save && payment_order.reload
|
||||||
|
|
||||||
|
assert @unpaid.payment_orders.last.payment_reference?
|
||||||
|
|
||||||
|
InvoiceStateMachine.new(invoice: @unpaid, status: 'unpaid').call
|
||||||
|
@unpaid.reload
|
||||||
|
|
||||||
|
assert @unpaid.paid?
|
||||||
|
assert @unpaid.errors.present?
|
||||||
|
assert_equal @unpaid.errors.full_messages.join, 'Inavalid state unpaid'
|
||||||
|
end
|
||||||
|
end
|
|
@ -6,6 +6,8 @@ class InvoiceTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
@invoice = invoices(:one)
|
@invoice = invoices(:one)
|
||||||
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
|
Spy.on_instance_method(EisBilling::BaseController, :authorized).and_return(true)
|
||||||
|
stub_request(:post, 'https://eis_billing_system:3000/api/v1/invoice_generator/invoice_status')
|
||||||
|
.to_return(status: :ok, headers: {})
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_fixture_is_valid
|
def test_fixture_is_valid
|
||||||
|
@ -117,32 +119,32 @@ class InvoiceTest < ActiveSupport::TestCase
|
||||||
transaction.sum = 250
|
transaction.sum = 250
|
||||||
|
|
||||||
invoice_n = Invoice.order(number: :desc).last.number
|
invoice_n = Invoice.order(number: :desc).last.number
|
||||||
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator")
|
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: {})
|
.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")
|
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: {})
|
.to_return(status: 200, body: '{"everypay_link":"http://link.test"}', headers: {})
|
||||||
|
|
||||||
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
|
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: {})
|
.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").
|
stub_request(:post, 'https://eis_billing_system:3000/api/v1/e_invoice/e_invoice')
|
||||||
to_return(status: 200, body: "", headers: {})
|
.to_return(status: 200, body: '', headers: {})
|
||||||
|
|
||||||
invoice = Invoice.create_from_transaction!(transaction)
|
invoice = Invoice.create_from_transaction!(transaction)
|
||||||
assert_equal 250, invoice.total
|
assert_equal 250, invoice.total
|
||||||
|
|
||||||
invoice_n = Invoice.order(number: :desc).last.number
|
invoice_n = Invoice.order(number: :desc).last.number
|
||||||
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
|
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: {})
|
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 4}\"}", headers: {})
|
||||||
|
|
||||||
transaction.sum = 146.88
|
transaction.sum = 146.88
|
||||||
invoice = Invoice.create_from_transaction!(transaction)
|
invoice = Invoice.create_from_transaction!(transaction)
|
||||||
assert_equal 146.88, invoice.total
|
assert_equal 146.88, invoice.total
|
||||||
|
|
||||||
invoice_n = Invoice.order(number: :desc).last.number
|
invoice_n = Invoice.order(number: :desc).last.number
|
||||||
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_number_generator").
|
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: {})
|
.to_return(status: 200, body: "{\"invoice_number\":\"#{invoice_n + 5}\"}", headers: {})
|
||||||
|
|
||||||
transaction.sum = 0.99
|
transaction.sum = 0.99
|
||||||
invoice = Invoice.create_from_transaction!(transaction)
|
invoice = Invoice.create_from_transaction!(transaction)
|
||||||
|
@ -151,14 +153,14 @@ class InvoiceTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
def test_emails_invoice_after_creating_topup_invoice
|
def test_emails_invoice_after_creating_topup_invoice
|
||||||
invoice_n = Invoice.order(number: :desc).last.number
|
invoice_n = Invoice.order(number: :desc).last.number
|
||||||
stub_request(:post, "https://eis_billing_system:3000/api/v1/invoice_generator/invoice_generator").
|
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: {})
|
.to_return(status: 200, body: '{"everypay_link":"http://link.test"}', headers: {})
|
||||||
|
|
||||||
stub_request(:put, "https://registry:3000/eis_billing/e_invoice_response").
|
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: {})
|
.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").
|
stub_request(:post, 'https://eis_billing_system:3000/api/v1/e_invoice/e_invoice')
|
||||||
to_return(status: 200, body: "", headers: {})
|
.to_return(status: 200, body: '', headers: {})
|
||||||
|
|
||||||
registrar = registrars(:bestnames)
|
registrar = registrars(:bestnames)
|
||||||
transaction = bank_transactions(:one).dup
|
transaction = bank_transactions(:one).dup
|
||||||
|
@ -172,4 +174,73 @@ class InvoiceTest < ActiveSupport::TestCase
|
||||||
Invoice.create_from_transaction!(transaction)
|
Invoice.create_from_transaction!(transaction)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_create_payment_order
|
||||||
|
everypay_response = {
|
||||||
|
'some' => 'some'
|
||||||
|
}
|
||||||
|
@invoice.payment_orders.delete_all
|
||||||
|
@invoice.account_activity.delete and @invoice.reload
|
||||||
|
assert @invoice.payment_orders.empty?
|
||||||
|
assert_nil @invoice.account_activity
|
||||||
|
|
||||||
|
@invoice.process_payment(payment_type: 'PaymentOrders::EveryPay',
|
||||||
|
everypay_response: everypay_response,
|
||||||
|
payment_status: 'paid',
|
||||||
|
sum: @invoice.total,
|
||||||
|
transaction_time: Time.zone.now - 10.minutes - 23.seconds)
|
||||||
|
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
assert_equal @invoice.payment_orders.count, 1
|
||||||
|
assert @invoice.account_activity.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_raise_error_if_bill_already_paid
|
||||||
|
everypay_response = {
|
||||||
|
'some' => 'some'
|
||||||
|
}
|
||||||
|
assert @invoice.payment_orders.present?
|
||||||
|
|
||||||
|
assert_raises(ActiveRecord::RecordInvalid) do
|
||||||
|
@invoice.process_payment(payment_type: 'PaymentOrders::EveryPay',
|
||||||
|
everypay_response: everypay_response,
|
||||||
|
payment_status: 'paid',
|
||||||
|
sum: @invoice.total,
|
||||||
|
transaction_time: Time.zone.now - 10.minutes - 23.seconds)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_manually_autobin_invoice
|
||||||
|
@invoice.payment_orders.destroy_all && @invoice.account_activity.destroy
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
account = @invoice.buyer.accounts.first
|
||||||
|
item = @invoice.items.first
|
||||||
|
|
||||||
|
assert @invoice.payment_orders.empty?
|
||||||
|
assert @invoice.account_activity.nil?
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
assert_equal item.price, 5.0
|
||||||
|
|
||||||
|
@invoice.autobind_manually
|
||||||
|
@invoice.reload
|
||||||
|
account.reload
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 105.0
|
||||||
|
assert @invoice.payment_orders.present?
|
||||||
|
assert @invoice.account_activity.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_cannot_to_increase_balance_already_paid_invoice_by_manually_autobind
|
||||||
|
assert @invoice.paid?
|
||||||
|
|
||||||
|
account = @invoice.buyer.accounts.first
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
|
||||||
|
@invoice.autobind_manually
|
||||||
|
@invoice.reload
|
||||||
|
|
||||||
|
assert_equal account.balance.to_f, 100.0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue