Make sure that Directo monthly invoice number frame is not exceeded

This commit is contained in:
Karl Erik Õunapuu 2020-02-19 11:53:15 +02:00
parent d5662f42b8
commit 98683f3bcc
3 changed files with 60 additions and 33 deletions

View file

@ -9,7 +9,7 @@ GIT
GIT GIT
remote: https://github.com/internetee/directo.git remote: https://github.com/internetee/directo.git
revision: 6ac71939da589fcceb5ef3989ba982134679ec97 revision: 41f4b49da2d4155a76ab57f1cb07bb1d0ba9cdef
branch: directo-api branch: directo-api
specs: specs:
directo (0.1.0) directo (0.1.0)

View file

@ -11,7 +11,7 @@ module BookKeeping
'customer_code': accounting_customer_code, 'customer_code': accounting_customer_code,
'language': language, 'language': language,
'currency': activities.first.currency, 'currency': activities.first.currency,
'date': month.end_of_month.strftime('%Y-%m-%d'), 'date': month.end_of_month.strftime('%Y-%m-%d')
}.as_json }.as_json
lines = [] lines = []
@ -43,12 +43,13 @@ module BookKeeping
end end
def new_montly_invoice_line(activity:, duration: nil) def new_montly_invoice_line(activity:, duration: nil)
price = DirectoInvoiceForwardJob.load_price(activity) price = load_price(activity)
yearly = price.duration.include?('year') yearly = price.duration.include?('year')
line = { line = {
'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym],
'quantity': 1, 'quantity': 1,
'price': yearly ? (price.price.amount / price.duration.to_i) : price.amount, 'price': yearly ? (price.price.amount / price.duration.to_i) : price.amount,
'unit': language == 'en' ? 'pc' : 'tk'
} }
line['description'] = description_in_language(price: price, yearly: yearly) line['description'] = description_in_language(price: price, yearly: yearly)
@ -59,8 +60,9 @@ module BookKeeping
def add_product_timeframe(line:, activity:, duration:) def add_product_timeframe(line:, activity:, duration:)
create_time = activity.created_at create_time = activity.created_at
line['start_date'] = (create_time + (duration - 1).year).end_of_month.strftime('%Y-%m-%d') start_date = (create_time + (duration - 1).year).end_of_month
line['end_date'] = (create_time + (duration - 1).year + 1).end_of_month.strftime('%Y-%m-%d') end_date = (create_time + (duration - 1).year + 1).end_of_month
line['period'] = start_date..end_date
end end
def description_in_language(price:, yearly:) def description_in_language(price:, yearly:)
@ -84,9 +86,10 @@ module BookKeeping
lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } lines.each { |l| total += l['quantity'].to_f * l['price'].to_f }
{ {
'product_id': Setting.directo_receipt_product_name, 'product_id': Setting.directo_receipt_product_name,
'description': 'Domeenide ettemaks', 'description': language == 'en' ? 'Domains prepayment' : 'Domeenide ettemaks',
'quantity': -1, 'quantity': -1,
'price': total 'price': total,
'unit': language == 'en' ? 'pc' : 'tk'
} }
end end

View file

@ -1,6 +1,7 @@
class DirectoInvoiceForwardJob < Que::Job class DirectoInvoiceForwardJob < Que::Job
def run(monthly: false, dry: false) def run(monthly: false, dry: false)
@dry = dry @dry = dry
@monthly = monthly
api_url = ENV['directo_invoice_url'] api_url = ENV['directo_invoice_url']
sales_agent = Setting.directo_sales_agent sales_agent = Setting.directo_sales_agent
payment_term = Setting.directo_receipt_payment_term payment_term = Setting.directo_receipt_payment_term
@ -26,7 +27,7 @@ class DirectoInvoiceForwardJob < Que::Job
end end
def send_monthly_invoices def send_monthly_invoices
month = Time.now - 1.month month = Time.now
Registrar.where.not(test_registrar: true).find_each do |registrar| Registrar.where.not(test_registrar: true).find_each do |registrar|
next unless registrar.cash_account next unless registrar.cash_account
@ -35,10 +36,25 @@ class DirectoInvoiceForwardJob < Que::Job
@client.invoices.add_with_schema(invoice: invoice, schema: 'summary') @client.invoices.add_with_schema(invoice: invoice, schema: 'summary')
end end
# TODO: Invoice number assign_montly_numbers
sync_with_directo sync_with_directo
end end
def assign_montly_numbers
if directo_counter_exceedable?(@client.invoices.count)
raise 'Directo Counter is going to be out of period!'
end
min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
directo_number = [Setting.directo_monthly_number_last.presence.try(:to_i),
min_directo].compact.max || 0
@client.invoices.each do |inv|
directo_number += 1
inv.number = directo_number
end
end
def valid_invoice_conditions?(invoice) def valid_invoice_conditions?(invoice)
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? || if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum.nil? ||
@ -57,45 +73,53 @@ class DirectoInvoiceForwardJob < Que::Job
return if @dry return if @dry
res = @client.invoices.deliver(ssl_verify: false) res = @client.invoices.deliver(ssl_verify: false)
update_invoice_directo_state(res.body, @client.invoices.as_xml) if res.code == '200'
update_invoice_directo_state(res.body) if res.code == '200'
rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError
Rails.logger.info("[Directo] Failed. Responded with code: #{res.code}, body: #{res.body}") Rails.logger.info('[Directo] Failed to communicate via API')
end end
def update_invoice_directo_state(xml) def update_invoice_directo_state(xml, req)
Rails.logger.info "[Directo] - Responded with body: #{xml}"
Nokogiri::XML(xml).css('Result').each do |res| Nokogiri::XML(xml).css('Result').each do |res|
inv = Invoice.find_by(number: res.attributes['docid'].value.to_i) if @monthly
mark_invoice_as_sent(invoice: inv, data: res) 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
end end
def mark_invoice_as_sent(invoice:, data:) def mark_invoice_as_sent(invoice: nil, res:, req:)
invoice.directo_records.create!(response: data.as_json.to_h, invoice_number: invoice.number) directo_record = Directo.new(response: res.as_json.to_h,
invoice.update_columns(in_directo: true) request: req, invoice_number: res.attributes['docid'].value.to_i)
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} was pushed and return is #{data.as_json.to_h.inspect}") if invoice
end directo_record.invoice = invoice
invoice.update_columns(in_directo: true)
def self.load_price(account_activity) else
@pricelists ||= {} update_directo_number(num: directo_record.invoice_number)
if @pricelists.key? account_activity.price_id
return @pricelists[account_activity.price_id]
end end
@pricelists[account_activity.price_id] = account_activity.price directo_record.save!
end end
def last_directo_monthly_number def update_directo_number(num:)
return unless num.to_i > Setting.directo_monthly_number_last
Setting.directo_monthly_number_last = num
end
def directo_counter_exceedable?(invoice_count)
min_directo = Setting.directo_monthly_number_min.presence.try(:to_i) min_directo = Setting.directo_monthly_number_min.presence.try(:to_i)
max_directo = Setting.directo_monthly_number_max.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] last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i),
.compact.max || 0 min_directo].compact.max || 0
if max_directo && max_directo <= last_directo if max_directo && max_directo < (last_directo + invoice_count)
raise 'Directo counter is out of period' true
else
false
end end
last_directo
end end
end end