From 98683f3bcc8111c8533d1c9e56d1c0a6dbeb488f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Erik=20=C3=95unapuu?= Date: Wed, 19 Feb 2020 11:53:15 +0200 Subject: [PATCH] Make sure that Directo monthly invoice number frame is not exceeded --- Gemfile.lock | 2 +- app/controllers/concerns/book_keeping.rb | 15 +++-- app/jobs/directo_invoice_forward_job.rb | 76 ++++++++++++++++-------- 3 files changed, 60 insertions(+), 33 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 71abcf70d..e6b82297c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ GIT GIT remote: https://github.com/internetee/directo.git - revision: 6ac71939da589fcceb5ef3989ba982134679ec97 + revision: 41f4b49da2d4155a76ab57f1cb07bb1d0ba9cdef branch: directo-api specs: directo (0.1.0) diff --git a/app/controllers/concerns/book_keeping.rb b/app/controllers/concerns/book_keeping.rb index 4e25a466f..284b6db71 100644 --- a/app/controllers/concerns/book_keeping.rb +++ b/app/controllers/concerns/book_keeping.rb @@ -11,7 +11,7 @@ module BookKeeping 'customer_code': accounting_customer_code, 'language': language, 'currency': activities.first.currency, - 'date': month.end_of_month.strftime('%Y-%m-%d'), + 'date': month.end_of_month.strftime('%Y-%m-%d') }.as_json lines = [] @@ -43,12 +43,13 @@ module BookKeeping end def new_montly_invoice_line(activity:, duration: nil) - price = DirectoInvoiceForwardJob.load_price(activity) + price = load_price(activity) yearly = price.duration.include?('year') line = { 'product_id': DOMAIN_TO_PRODUCT[price.zone_name.to_sym], 'quantity': 1, '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) @@ -59,8 +60,9 @@ module BookKeeping 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') + start_date = (create_time + (duration - 1).year).end_of_month + end_date = (create_time + (duration - 1).year + 1).end_of_month + line['period'] = start_date..end_date end def description_in_language(price:, yearly:) @@ -84,9 +86,10 @@ module BookKeeping lines.each { |l| total += l['quantity'].to_f * l['price'].to_f } { 'product_id': Setting.directo_receipt_product_name, - 'description': 'Domeenide ettemaks', + 'description': language == 'en' ? 'Domains prepayment' : 'Domeenide ettemaks', 'quantity': -1, - 'price': total + 'price': total, + 'unit': language == 'en' ? 'pc' : 'tk' } end diff --git a/app/jobs/directo_invoice_forward_job.rb b/app/jobs/directo_invoice_forward_job.rb index 6eca4c73c..ff584914d 100644 --- a/app/jobs/directo_invoice_forward_job.rb +++ b/app/jobs/directo_invoice_forward_job.rb @@ -1,6 +1,7 @@ class DirectoInvoiceForwardJob < Que::Job def run(monthly: false, dry: false) @dry = dry + @monthly = monthly api_url = ENV['directo_invoice_url'] sales_agent = Setting.directo_sales_agent payment_term = Setting.directo_receipt_payment_term @@ -26,7 +27,7 @@ class DirectoInvoiceForwardJob < Que::Job end def send_monthly_invoices - month = Time.now - 1.month + month = Time.now Registrar.where.not(test_registrar: true).find_each do |registrar| next unless registrar.cash_account @@ -35,10 +36,25 @@ class DirectoInvoiceForwardJob < Que::Job @client.invoices.add_with_schema(invoice: invoice, schema: 'summary') end - # TODO: Invoice number + assign_montly_numbers sync_with_directo 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) if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? || invoice.account_activity.bank_transaction.sum.nil? || @@ -57,45 +73,53 @@ class DirectoInvoiceForwardJob < Que::Job return if @dry res = @client.invoices.deliver(ssl_verify: false) - - update_invoice_directo_state(res.body) if res.code == '200' + update_invoice_directo_state(res.body, @client.invoices.as_xml) if res.code == '200' rescue SocketError, Errno::ECONNREFUSED, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, 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 - 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| - inv = Invoice.find_by(number: res.attributes['docid'].value.to_i) - mark_invoice_as_sent(invoice: inv, data: res) + if @monthly + 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:, data:) - invoice.directo_records.create!(response: data.as_json.to_h, invoice_number: invoice.number) - invoice.update_columns(in_directo: true) - Rails.logger.info("[DIRECTO] Invoice #{invoice.number} was pushed and return is #{data.as_json.to_h.inspect}") - end - - def self.load_price(account_activity) - @pricelists ||= {} - if @pricelists.key? account_activity.price_id - return @pricelists[account_activity.price_id] + 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.invoice = invoice + invoice.update_columns(in_directo: true) + else + update_directo_number(num: directo_record.invoice_number) end - @pricelists[account_activity.price_id] = account_activity.price + directo_record.save! 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) 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 + last_directo = [Setting.directo_monthly_number_last.presence.try(:to_i), + min_directo].compact.max || 0 - if max_directo && max_directo <= last_directo - raise 'Directo counter is out of period' + if max_directo && max_directo < (last_directo + invoice_count) + true + else + false end - - last_directo end end