Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added e-invoicing feature to invoices #1151

Merged
merged 3 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions app/controllers/eis_billing/e_invoice_response_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module EisBilling
class 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
end
11 changes: 11 additions & 0 deletions app/controllers/invoices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ def oneoff
end
end

def send_e_invoice
invoice = Invoice.accessible_by(current_ability).find_by!(uuid: params[:uuid])
response = EisBilling::SendEInvoice.call(invoice: invoice, payable: false)

if response.result?
redirect_to invoice_path(invoice.uuid), notice: t('.sent_to_omniva')
else
redirect_to invoice_path(invoice.uuid), alert: response.errors
end
end

def update_predicate
@invoice.issued? && @invoice.update(update_params)
end
Expand Down
88 changes: 86 additions & 2 deletions app/models/concerns/invoice/book_keeping.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,88 @@ def as_directo_json
invoice
end

def e_invoice_data
invoice = as_json(only: %i[id issue_date due_date number])
invoice['seller_name'] = seller_contact_name
invoice['seller_reg_no'] = seller_reg_no
invoice['seller_vat_no'] = seller_vat_no
invoice['seller_street'] = seller_street
invoice['seller_state'] = seller_state
invoice['seller_zip'] = seller_zip
invoice['seller_city'] = seller_city
invoice['seller_country_code'] = seller_country_code
invoice['buyer_name'] = billing_name
invoice['buyer_vat_no'] = billing_vat_code
invoice['buyer_street'] = street
invoice['buyer_state'] = state
invoice['buyer_zip'] = postal_code
invoice['buyer_city'] = city
invoice['buyer_country_code'] = billing_alpha_two_country_code
invoice['total'] = total.to_f + (enable_deposit? ? deposit : 0.0)
invoice['vat_rate'] = vat_rate * 100
invoice['currency'] = Setting.find_by(code: 'auction_currency').retrieve

invoice
end

def e_invoice_sent?
e_invoice_sent_at.present?
end

def do_not_send_e_invoice?
e_invoice_sent? || cancelled?
end

def seller_contact_name
Setting.find_by(code: 'invoice_issuer').retrieve
end

def seller_address
country_name = Countries.name_from_alpha2_code(seller_country_code)
[
seller_street,
seller_state,
seller_zip,
country_name,
seller_city
].reject(&:blank?).compact.join(', ')
end

def seller_reg_no
Setting.find_by(code: 'invoice_issuer_reg_no').retrieve
end

def seller_vat_no
Setting.find_by(code: 'invoice_issuer_vat_no').retrieve
end

def seller_street
Setting.find_by(code: 'invoice_issuer_street').retrieve
end

def seller_city
Setting.find_by(code: 'invoice_issuer_city').retrieve
end

def seller_zip
Setting.find_by(code: 'invoice_issuer_zip').retrieve
end

def seller_country_code
Setting.find_by(code: 'invoice_issuer_country_code').retrieve
end

def seller_state
Setting.find_by(code: 'invoice_issuer_state').retrieve
end

def issuer
"#{seller_contact_name}, #{seller_address}, " \
"Reg. no #{seller_reg_no}, VAT number #{seller_vat_no}"
end

private

def compose_invoice_meta(invoice)
invoice['issue_date'] = issue_date.strftime('%Y-%m-%d')
invoice['transaction_date'] = paid_at.strftime('%Y-%m-%d')
Expand All @@ -36,12 +118,14 @@ def compose_directo_customer
end

def compose_directo_product
[{ 'product_id': 'OKSJON',
[
{ 'product_id': 'OKSJON',
'description': result.auction.domain_name,
'quantity': 1,
'unit': 1,
'price': ActionController::Base.helpers.number_with_precision(
price.amount, precision: 2, separator: '.'
) }].as_json
) }
].as_json
end
end
6 changes: 6 additions & 0 deletions app/services/application_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# app/services/application_service.rb
class ApplicationService
def self.call(*args, &block)
new(*args, &block).call
end
end
53 changes: 53 additions & 0 deletions app/services/eis_billing/send_e_invoice.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module EisBilling
class SendEInvoice < ApplicationService
include EisBilling::Request
include EisBilling::BaseService

attr_reader :invoice, :payable

def initialize(invoice:, payable:)
@invoice = invoice
@payable = payable
end

def call
prepared_data = {
invoice: invoice.e_invoice_data,
vat_amount: invoice.vat.amount,
invoice_subtotal: invoice.price.amount,
buyer_billing_email: invoice.user&.email,
payable: payable,
initiator: INITIATOR,
items: prepare_items(invoice)
}

struct_response(post(e_invoice_url, prepared_data))
end

private

def prepare_items(invoice)
invoice.items.map do |invoice_item|
{
description: item_description(invoice.result),
price: invoice_item.price.amount,
quantity: 1,
unit: 'piece',
subtotal: invoice_item.price.amount,
vat_rate: invoice.vat_rate.to_f * 100,
vat_amount: invoice.vat.amount,
total: invoice.total.to_f,
}
end
end

def e_invoice_url
'/api/v1/e_invoice/e_invoice'
end

def item_description(result)
I18n.t('invoice_items.name', domain_name: result.auction.domain_name,
auction_end: result.auction.ends_at.to_date)
end
end
end
4 changes: 2 additions & 2 deletions app/views/common/pdf.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@
<%= t('invoices.issuer') %>
</dt>
<dd>
<%= Setting.find_by(code: 'invoice_issuer').retrieve %>
<%= @invoice.issuer %>
</dd>
<dt>
<%= t('invoices.number') %>
Expand Down Expand Up @@ -301,7 +301,7 @@
<hr/>
<div class="row">
<div class="col-md-6 left">
<%= Setting.find_by(code: 'invoice_issuer').retrieve %>
<%= @invoice.issuer %>
</div>
</div>
</div>
Expand Down
22 changes: 15 additions & 7 deletions app/views/invoices/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@
<div class="ui list">
<div class="item">
<div class="header"><%= t('invoices.issuer') %></div>
<%= Setting.find_by(code: 'invoice_issuer').retrieve %>
</div>
<%= @invoice.issuer %>
</div>
<div class="item">
<div class="header"><%= t('invoices.issue_date') %></div>
<%= @invoice.issue_date %>
<%= @invoice.issue_date %>
</div>
<div class="item">
<div class="header"><%= t('invoices.due_date') %></div>
<%= @invoice.due_date %>
<%= @invoice.due_date %>
</div>
<% if @invoice.paid? %>
<div class="item">
Expand All @@ -62,8 +62,8 @@
<td><%= index + 1 %></td>
<td>
<%= I18n.t('invoice_items.name',
domain_name: item.invoice.result.auction.domain_name,
auction_end: item.invoice.result.auction.ends_at.to_date) %>
domain_name: @invoice.result.auction.domain_name,
auction_end: @invoice.result.auction.ends_at.to_date) %>
</td>
<td></td>
<td><%= item.price %></td>
Expand Down Expand Up @@ -104,10 +104,18 @@
</table>
</div>
<% if @invoice.payable? %>
<div>
<div class="column">
<%= button_to t('invoices.show.pay'), oneoff_invoice_path(uuid: @invoice.uuid), class: 'ui button primary' %>
</div>
<% end %>
<div class="column right aligned">
<% if @invoice.do_not_send_e_invoice? %>
<a href="https://eservice.omniva.eu" target="_blank"><img src="/images/finbite.png" alt="EInvoice" style="height:40px;"/></a>
<% else %>
<%= button_to t('invoices.show.send_e_invoice'), send_e_invoice_path(uuid: @invoice.uuid), class: 'ui button default', data: { turbo: false } %>
<% end %>
</div>
</div>
</div>
</div>
</div>
11 changes: 0 additions & 11 deletions config/customization.yml.sample
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
default: &default
billing_system_integration:
enabled: true
#eis_billing_system_base_url_dev: 'http://eis_billing_system:3000'
#eis_billing_system_base_url_staging: 'https://st-billing.infra.tld.ee'
eis_billing_system_base_url: 'http://eis_billing_system:3000'
secret_access_word: 'please-Give-Me-accesS'
secret_word: 'this-secret-should-be-change'
billing_system_integrated: 'true'

billing_secret: '0fb3661d89134de0cbcdd6b29780e23f2ec05e744c4d15feb381b1e7d7549d5ec960989c6471c9a31835ee455865cf7b2641529ae7cf1e6b4c3675f6361e98d0'
# This is your application name, as displayed in the UI
application_name: "EIS Auction Center"

Expand Down Expand Up @@ -124,7 +114,6 @@ default: &default
secret_word: 'this-secret-should-be-change'
billing_system_integrated: 'true'
billing_secret: ''
test_env: false

development:
<<: *default
Expand Down
2 changes: 2 additions & 0 deletions config/locales/invoices.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ en:
paid_through: "Paid through"
deposit: "Deposit"
amount_due: "Amount due"
sent_to_omniva: "E-Invoice was successfully sent"

outstanding: "Outstanding invoices"
paid: "Paid invoices"
Expand All @@ -49,6 +50,7 @@ en:
change_billing_profile: "Change billing profile"
pay: "Pay"
redeem: Paying for cancelled invoice will redeem the violation but will not grant priority right to register that domain
send_e_invoice: "Send E-Invoice"

edit:
title: "Edit your invoice"
Expand Down
2 changes: 2 additions & 0 deletions config/locales/invoices.et.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ et:
paid_through: "Makseviis"
deposit: "Ettemaks"
amount_due: "Tasuda"
sent_to_omniva: "E-arve saadeti edukalt"

outstanding: "Tasumata arved"
paid: "Tasutud arved"
Expand All @@ -49,6 +50,7 @@ et:
change_billing_profile: "Muuda arve aadressi"
pay: "Maksa"
redeem: Tühistatud arve tasumine eemaldab vastava arvega seotud rikkumise, kuid ei anna vastava domeeni registreerimiseks eelisõigust.
send_e_invoice: "Saada E-Arve"

edit:
title: "Muuda arvet"
Expand Down
3 changes: 2 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
namespace :eis_billing, defaults: { format: 'json' } do
put '/payment_status', to: 'payment_status#update', as: 'payment_status'
put '/directo_response', to: 'directo_response#update', as: 'directo_response'
put '/e_invoice_response', to: 'e_invoice_response#update', as: 'e_invoice_response'
end

namespace :admin, constraints: Constraints::Administrator.new do
Expand Down Expand Up @@ -90,11 +91,11 @@
resources :billing_profiles, param: :uuid
match '/status', via: :get, to: 'health_checks#index'


resources :invoices, only: %i[show edit update index], param: :uuid do
member do
get 'download'
post 'oneoff'
post 'send_e_invoice', as: :send_e
end

collection do
Expand Down
Loading