2019-09-19 14:59:22 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2020-12-22 14:43:08 +01:00
|
|
|
# Provides methods to generate Invoice, Avoir or PaymentSchedule references
|
|
|
|
class PaymentDocumentService
|
2019-09-19 14:59:22 +02:00
|
|
|
class << self
|
2020-12-22 14:43:08 +01:00
|
|
|
def generate_reference(document, date: DateTime.current)
|
2020-05-13 15:02:03 +02:00
|
|
|
pattern = Setting.get('invoice_reference')
|
2019-09-19 14:59:22 +02:00
|
|
|
|
2022-04-11 19:00:50 +02:00
|
|
|
reference = replace_invoice_number_pattern(pattern, document.created_at)
|
2019-09-19 14:59:22 +02:00
|
|
|
reference = replace_date_pattern(reference, date)
|
|
|
|
|
2021-04-26 11:40:26 +02:00
|
|
|
if document.is_a? Avoir
|
2019-09-19 14:59:22 +02:00
|
|
|
# information about refund/avoir (R[text])
|
|
|
|
reference.gsub!(/R\[([^\]]+)\]/, '\1')
|
|
|
|
|
|
|
|
# remove information about online selling (X[text])
|
|
|
|
reference.gsub!(/X\[([^\]]+)\]/, ''.to_s)
|
2020-11-17 16:23:55 +01:00
|
|
|
# remove information about payment schedule (S[text])
|
|
|
|
reference.gsub!(/S\[([^\]]+)\]/, ''.to_s)
|
2021-04-26 11:40:26 +02:00
|
|
|
elsif document.is_a? PaymentSchedule
|
2020-11-16 16:37:40 +01:00
|
|
|
# information about payment schedule
|
|
|
|
reference.gsub!(/S\[([^\]]+)\]/, '\1')
|
|
|
|
# remove information about online selling (X[text])
|
|
|
|
reference.gsub!(/X\[([^\]]+)\]/, ''.to_s)
|
|
|
|
# remove information about refunds (R[text])
|
|
|
|
reference.gsub!(/R\[([^\]]+)\]/, ''.to_s)
|
2021-04-26 11:40:26 +02:00
|
|
|
elsif document.is_a? Invoice
|
2019-09-19 14:59:22 +02:00
|
|
|
# information about online selling (X[text])
|
2021-04-20 17:22:53 +02:00
|
|
|
if document.paid_by_card?
|
2019-09-19 14:59:22 +02:00
|
|
|
reference.gsub!(/X\[([^\]]+)\]/, '\1')
|
|
|
|
else
|
|
|
|
reference.gsub!(/X\[([^\]]+)\]/, ''.to_s)
|
|
|
|
end
|
|
|
|
|
|
|
|
# remove information about refunds (R[text])
|
|
|
|
reference.gsub!(/R\[([^\]]+)\]/, ''.to_s)
|
2020-11-17 16:23:55 +01:00
|
|
|
# remove information about payment schedule (S[text])
|
|
|
|
reference.gsub!(/S\[([^\]]+)\]/, ''.to_s)
|
2020-12-22 14:43:08 +01:00
|
|
|
else
|
|
|
|
raise TypeError
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
reference
|
|
|
|
end
|
|
|
|
|
|
|
|
def generate_order_number(invoice)
|
2020-05-13 15:02:03 +02:00
|
|
|
pattern = Setting.get('invoice_order-nb')
|
2019-09-19 14:59:22 +02:00
|
|
|
|
2020-12-22 14:43:08 +01:00
|
|
|
# global document number (nn..nn)
|
2019-09-19 14:59:22 +02:00
|
|
|
reference = pattern.gsub(/n+(?![^\[]*\])/) do |match|
|
2020-11-16 16:37:40 +01:00
|
|
|
pad_and_truncate(number_of_invoices('global'), match.to_s.length)
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
|
|
|
|
2022-04-11 19:00:50 +02:00
|
|
|
reference = replace_invoice_number_pattern(reference, invoice.created_at)
|
2019-09-19 14:59:22 +02:00
|
|
|
replace_date_pattern(reference, invoice.created_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
##
|
|
|
|
# Output the given integer with leading zeros. If the given value is longer than the given
|
|
|
|
# length, it will be truncated.
|
|
|
|
# @param value {Integer} the integer to pad
|
|
|
|
# @param length {Integer} the length of the resulting string.
|
|
|
|
##
|
|
|
|
def pad_and_truncate(value, length)
|
|
|
|
value.to_s.rjust(length, '0').gsub(/^.*(.{#{length},}?)$/m, '\1')
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Returns the number of current invoices in the given range around the current date.
|
|
|
|
# If range is invalid or not specified, the total number of invoices is returned.
|
|
|
|
# @param range {String} 'day', 'month', 'year'
|
2022-04-11 19:00:50 +02:00
|
|
|
# @param date {Date} the ending date
|
2019-09-19 14:59:22 +02:00
|
|
|
# @return {Integer}
|
|
|
|
##
|
2022-04-11 19:00:50 +02:00
|
|
|
def number_of_invoices(range, date = DateTime.current)
|
2019-09-19 14:59:22 +02:00
|
|
|
case range.to_s
|
|
|
|
when 'day'
|
2022-04-11 19:00:50 +02:00
|
|
|
start = date.beginning_of_day
|
2019-09-19 14:59:22 +02:00
|
|
|
when 'month'
|
2022-04-11 19:00:50 +02:00
|
|
|
start = date.beginning_of_month
|
2019-09-19 14:59:22 +02:00
|
|
|
when 'year'
|
2022-04-11 19:00:50 +02:00
|
|
|
start = date.beginning_of_year
|
2019-09-19 14:59:22 +02:00
|
|
|
else
|
2020-11-16 16:37:40 +01:00
|
|
|
return get_max_id(Invoice) + get_max_id(PaymentSchedule)
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
2022-04-11 19:00:50 +02:00
|
|
|
ending = date
|
|
|
|
return Invoice.count + PaymentSchedule.count unless defined? start
|
2019-09-19 14:59:22 +02:00
|
|
|
|
2022-04-11 19:00:50 +02:00
|
|
|
Invoice.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length +
|
|
|
|
PaymentSchedule.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Replace the date elements in the provided pattern with the date values, from the provided date
|
|
|
|
# @param reference {string}
|
|
|
|
# @param date {DateTime}
|
|
|
|
##
|
|
|
|
def replace_date_pattern(reference, date)
|
|
|
|
copy = reference.dup
|
|
|
|
|
|
|
|
# full year (YYYY)
|
|
|
|
copy.gsub!(/YYYY(?![^\[]*\])/, date.strftime('%Y'))
|
|
|
|
# year without century (YY)
|
|
|
|
copy.gsub!(/YY(?![^\[]*\])/, date.strftime('%y'))
|
|
|
|
|
|
|
|
# abbreviated month name (MMM)
|
|
|
|
copy.gsub!(/MMM(?![^\[]*\])/, date.strftime('%^b'))
|
|
|
|
# month of the year, zero-padded (MM)
|
|
|
|
copy.gsub!(/MM(?![^\[]*\])/, date.strftime('%m'))
|
|
|
|
# month of the year, non zero-padded (M)
|
|
|
|
copy.gsub!(/M(?![^\[]*\])/, date.strftime('%-m'))
|
|
|
|
|
|
|
|
# day of the month, zero-padded (DD)
|
|
|
|
copy.gsub!(/DD(?![^\[]*\])/, date.strftime('%d'))
|
|
|
|
# day of the month, non zero-padded (DD)
|
|
|
|
copy.gsub!(/DD(?![^\[]*\])/, date.strftime('%-d'))
|
|
|
|
|
|
|
|
copy
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
2020-12-22 14:43:08 +01:00
|
|
|
# Replace the document number elements in the provided pattern with counts from the database
|
2019-09-19 14:59:22 +02:00
|
|
|
# @param reference {string}
|
|
|
|
##
|
2022-04-11 19:00:50 +02:00
|
|
|
def replace_invoice_number_pattern(reference, date)
|
2019-09-19 14:59:22 +02:00
|
|
|
copy = reference.dup
|
|
|
|
|
2020-12-22 14:43:08 +01:00
|
|
|
# document number per year (yy..yy)
|
2019-09-19 14:59:22 +02:00
|
|
|
copy.gsub!(/y+(?![^\[]*\])/) do |match|
|
2022-04-11 19:00:50 +02:00
|
|
|
pad_and_truncate(number_of_invoices('year', date), match.to_s.length)
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
2020-12-22 14:43:08 +01:00
|
|
|
# document number per month (mm..mm)
|
2019-09-19 14:59:22 +02:00
|
|
|
copy.gsub!(/m+(?![^\[]*\])/) do |match|
|
2022-04-11 19:00:50 +02:00
|
|
|
pad_and_truncate(number_of_invoices('month', date), match.to_s.length)
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
2020-12-22 14:43:08 +01:00
|
|
|
# document number per day (dd..dd)
|
2019-09-19 14:59:22 +02:00
|
|
|
copy.gsub!(/d+(?![^\[]*\])/) do |match|
|
2022-04-11 19:00:50 +02:00
|
|
|
pad_and_truncate(number_of_invoices('day', date), match.to_s.length)
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
copy
|
|
|
|
end
|
2020-11-16 16:37:40 +01:00
|
|
|
|
|
|
|
##
|
|
|
|
# Return the maximum ID from the database, for the given class
|
|
|
|
# @param klass {ActiveRecord::Base}
|
|
|
|
##
|
|
|
|
def get_max_id(klass)
|
2020-11-17 16:23:55 +01:00
|
|
|
ActiveRecord::Base.connection.execute("SELECT max(id) FROM #{klass.table_name}").getvalue(0, 0) || 0
|
2020-11-16 16:37:40 +01:00
|
|
|
end
|
2019-09-19 14:59:22 +02:00
|
|
|
end
|
|
|
|
end
|