From 3f92640ad2f24a92c8bf746afb4cf52e90e11e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Mon, 2 Mar 2020 13:54:46 +0200 Subject: [PATCH] Move registrar directo logic to concern, touch up translations --- app/controllers/concerns/book_keeping.rb | 121 ------------------ app/jobs/directo_invoice_forward_job.rb | 6 +- app/models/concerns/invoice/book_keeping.rb | 25 ++++ app/models/concerns/registrar/book_keeping.rb | 120 +++++++++++++++++ app/models/invoice.rb | 19 +-- app/models/registrar.rb | 2 +- config/locales/registrars.en.yml | 3 +- config/locales/registrars.et.yml | 7 +- 8 files changed, 156 insertions(+), 147 deletions(-) delete mode 100644 app/controllers/concerns/book_keeping.rb create mode 100644 app/models/concerns/invoice/book_keeping.rb create mode 100644 app/models/concerns/registrar/book_keeping.rb diff --git a/app/controllers/concerns/book_keeping.rb b/app/controllers/concerns/book_keeping.rb deleted file mode 100644 index f50393822..000000000 --- a/app/controllers/concerns/book_keeping.rb +++ /dev/null @@ -1,121 +0,0 @@ -module BookKeeping - extend ActiveSupport::Concern - - DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI', - 'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze - - def monthly_summary(month:) - activities = monthly_activites(month) - return unless activities.any? - - inv = { - 'number': 1, - 'customer_code': accounting_customer_code, - 'language': language, 'currency': activities.first.currency, - 'date': month.end_of_month.strftime('%Y-%m-%d') - }.as_json - - inv['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities) - - inv - end - - def prepare_invoice_lines(month:, activities:) - lines = [] - - lines << { 'description': title_for_summary(month) } - activities.each do |activity| - fetch_invoice_lines(activity, lines) - end - lines << prepayment_for_all(lines) - - lines.as_json - end - - def title_for_summary(date) - if language == 'en' - I18n.with_locale('en') do - "Domains registrations - #{I18n.l(date, format: '%B %Y')}" - end - else - I18n.with_locale('et') do - "Domeenide registreerimine - #{I18n.l(date, format: '%B %Y')}" - end - end - end - - def fetch_invoice_lines(activity, lines) - price = load_price(activity) - if price.duration.include? 'year' - price.duration.to_i.times do |duration| - lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json - end - else - lines << new_monthly_invoice_line(activity: activity).as_json - end - end - - def monthly_activites(month) - AccountActivity.where(account_id: account_ids) - .where(created_at: month.beginning_of_month..month.end_of_month) - .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]) - end - - def new_monthly_invoice_line(activity:, duration: nil) - price = load_price(activity) - line = { - 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], - 'quantity': 1, - 'unit': language == 'en' ? 'pc' : 'tk', - } - - finalize_invoice_line(line, price: price, duration: duration, activity: activity) - end - - def finalize_invoice_line(line, price:, activity:, duration:) - yearly = price.duration.include?('year') - - line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount - line['description'] = description_in_language(price: price, yearly: yearly) - - if duration.present? - add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1 - end - - line - end - - def add_product_timeframe(line:, activity:, duration:) - create_time = activity.created_at - line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d') - line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d') - end - - def description_in_language(price:, yearly:) - timeframe_string = yearly ? 'yearly' : 'monthly' - locale_string = ".registrars.invoice_#{timeframe_string}_product_description" - - I18n.with_locale(language == 'en' ? 'en' : 'et') do - I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i) - end - end - - def prepayment_for_all(lines) - total = 0 - lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } - { - 'product_id': Setting.directo_receipt_product_name, - 'description': language == 'en' ? 'Domains prepayment' : 'Domeenide ettemaks', - 'quantity': -1, - 'price': total, - 'unit': language == 'en' ? 'pc' : 'tk', - } - end - - def load_price(account_activity) - @pricelists ||= {} - return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id - - @pricelists[account_activity.price_id] = account_activity.price - end -end diff --git a/app/jobs/directo_invoice_forward_job.rb b/app/jobs/directo_invoice_forward_job.rb index a423ffc2e..6c3eb034c 100644 --- a/app/jobs/directo_invoice_forward_job.rb +++ b/app/jobs/directo_invoice_forward_job.rb @@ -70,18 +70,18 @@ class DirectoInvoiceForwardJob < Que::Job end def sync_with_directo + assign_monthly_numbers if @month Rails.logger.info("[Directo] - attempting to send following XML:\n #{@client.invoices.as_xml}") return if @dry - assign_monthly_numbers if @month res = @client.invoices.deliver(ssl_verify: false) - update_invoice_directo_state(res.body, @client.invoices.as_xml) if res.code == '200' + process_directo_response(res.body, @client.invoices.as_xml) rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError Rails.logger.info('[Directo] Failed to communicate via API') end - def update_invoice_directo_state(xml, req) + def process_directo_response(xml, req) Rails.logger.info "[Directo] - Responded with body: #{xml}" Nokogiri::XML(xml).css('Result').each do |res| if @month diff --git a/app/models/concerns/invoice/book_keeping.rb b/app/models/concerns/invoice/book_keeping.rb new file mode 100644 index 000000000..828ad7848 --- /dev/null +++ b/app/models/concerns/invoice/book_keeping.rb @@ -0,0 +1,25 @@ +module Concerns + module Invoice + module BookKeeping + extend ActiveSupport::Concern + + def as_directo_json + inv = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self)) + inv['customer_code'] = buyer.accounting_customer_code + inv['issue_date'] = issue_date.strftime('%Y-%m-%d') + inv['transaction_date'] = account_activity.bank_transaction&.paid_at&.strftime('%Y-%m-%d') + inv['language'] = buyer.language == 'en' ? 'ENG' : '' + inv['invoice_lines'] = compose_directo_product + + inv + end + + def compose_directo_product + [{ 'product_id': Setting.directo_receipt_product_name, 'description': order, + 'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision( + subtotal, precision: 2, separator: '.' + ) }].as_json + end + end + end +end diff --git a/app/models/concerns/registrar/book_keeping.rb b/app/models/concerns/registrar/book_keeping.rb new file mode 100644 index 000000000..c85aac317 --- /dev/null +++ b/app/models/concerns/registrar/book_keeping.rb @@ -0,0 +1,120 @@ +module Concerns + module Registrar + module BookKeeping + extend ActiveSupport::Concern + + DOMAIN_TO_PRODUCT = { 'ee': '01EE', 'com.ee': '02COM', 'pri.ee': '03PRI', + 'fie.ee': '04FIE', 'med.ee': '05MED' }.freeze + + def monthly_summary(month:) + activities = monthly_activites(month) + return unless activities.any? + + inv = { + 'number': 1, + 'customer_code': accounting_customer_code, + 'language': language == 'en' ? 'ENG' : '', 'currency': activities.first.currency, + 'date': month.end_of_month.strftime('%Y-%m-%d') + }.as_json + + inv['invoice_lines'] = prepare_invoice_lines(month: month, activities: activities) + + inv + end + + def prepare_invoice_lines(month:, activities:) + lines = [] + + lines << { 'description': title_for_summary(month) } + activities.each do |activity| + fetch_invoice_lines(activity, lines) + end + lines << prepayment_for_all(lines) + + lines.as_json + end + + def title_for_summary(date) + I18n.with_locale(language == 'en' ? 'en' : 'et') do + I18n.t('registrar.monthly_summary_title', date: I18n.l(date, format: '%B %Y')) + end + end + + def fetch_invoice_lines(activity, lines) + price = load_price(activity) + if price.duration.include? 'year' + price.duration.to_i.times do |duration| + lines << new_monthly_invoice_line(activity: activity, duration: duration + 1).as_json + end + else + lines << new_monthly_invoice_line(activity: activity).as_json + end + end + + def monthly_activites(month) + AccountActivity.where(account_id: account_ids) + .where(created_at: month.beginning_of_month..month.end_of_month) + .where(activity_type: [AccountActivity::CREATE, AccountActivity::RENEW]) + end + + def new_monthly_invoice_line(activity:, duration: nil) + price = load_price(activity) + line = { + 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], + 'quantity': 1, + 'unit': language == 'en' ? 'pc' : 'tk', + } + + finalize_invoice_line(line, price: price, duration: duration, activity: activity) + end + + def finalize_invoice_line(line, price:, activity:, duration:) + yearly = price.duration.include?('year') + + line['price'] = yearly ? (price.price.amount / price.duration.to_i) : price.price.amount + line['description'] = description_in_language(price: price, yearly: yearly) + + if duration.present? + add_product_timeframe(line: line, activity: activity, duration: duration) if duration > 1 + end + + line + end + + def add_product_timeframe(line:, activity:, duration:) + create_time = activity.created_at + line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d') + line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d') + end + + def description_in_language(price:, yearly:) + timeframe_string = yearly ? 'yearly' : 'monthly' + locale_string = "registrar.invoice_#{timeframe_string}_product_description" + + I18n.with_locale(language == 'en' ? 'en' : 'et') do + I18n.t(locale_string, tld: ".#{price.zone_name}", length: price.duration.to_i) + end + end + + def prepayment_for_all(lines) + total = 0 + en = language == 'en' + lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } + { + 'product_id': Setting.directo_receipt_product_name, + 'description': en ? 'Domains prepayment' : 'Domeenide ettemaks', + 'quantity': -1, + 'price': total, + 'unit': en ? 'pc' : 'tk', + } + end + + def load_price(account_activity) + @pricelists ||= {} + return @pricelists[account_activity.price_id] if @pricelists.key? account_activity.price_id + + @pricelists[account_activity.price_id] = account_activity.price + end + end + end +end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 61b35ab98..7e1fee91b 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -2,6 +2,7 @@ class Invoice < ApplicationRecord include Versions include Concerns::Invoice::Cancellable include Concerns::Invoice::Payable + include Concerns::Invoice::BookKeeping belongs_to :buyer, class_name: 'Registrar' has_one :account_activity @@ -102,24 +103,6 @@ class Invoice < ApplicationRecord generator.generate end - def as_directo_json - inv = ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(self)) - inv['customer_code'] = buyer.accounting_customer_code - inv['issue_date'] = issue_date.strftime('%Y-%m-%d') - inv['transaction_date'] = account_activity.bank_transaction&.paid_at&.strftime('%Y-%m-%d') - inv['language'] = buyer.language - inv['invoice_lines'] = compose_directo_product - - inv - end - - def compose_directo_product - [{ 'product_id': Setting.directo_receipt_product_name, 'description': order, - 'quantity': 1, 'price': ActionController::Base.helpers.number_with_precision( - subtotal, precision: 2, separator: '.' - ) }].as_json - end - def do_not_send_e_invoice? e_invoice_sent? || cancelled? || paid? end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 8aae1e89e..c3522859e 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -1,6 +1,6 @@ class Registrar < ApplicationRecord include Versions # version/registrar_version.rb - include BookKeeping + include Concerns::Registrar::BookKeeping has_many :domains, dependent: :restrict_with_error has_many :contacts, dependent: :restrict_with_error diff --git a/config/locales/registrars.en.yml b/config/locales/registrars.en.yml index c5071c3f8..c57f2e891 100644 --- a/config/locales/registrars.en.yml +++ b/config/locales/registrars.en.yml @@ -1,7 +1,8 @@ en: - registrars: + registrar: invoice_yearly_product_description: '%{tld} registration: %{length} year(s)' invoice_monthly_product_description: '%{tld} registration: %{length} month(s)' + monthly_summary_title: 'Domain registrations - %{date}' activerecord: errors: models: diff --git a/config/locales/registrars.et.yml b/config/locales/registrars.et.yml index 4151183ea..1001638c1 100644 --- a/config/locales/registrars.et.yml +++ b/config/locales/registrars.et.yml @@ -1,4 +1,5 @@ et: - registrars: - invoice_yearly_product_description: '%{tld} registration: %{length} year(s)' - invoice_monthly_product_description: '%{tld} registration: %{length} month(s)' + registrar: + invoice_yearly_product_description: '%{tld} registreerimine: %{length} aasta(t)' + invoice_monthly_product_description: '%{tld} registreerimine: %{length} kuu(d)' + monthly_summary_title: 'Domeenide registreerimine - %{date}'