1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
# frozen_string_literal: true
module Faker
class Invoice < Base
flexible :invoice
class << self
##
# Produces a random amount between values with 2 decimals
#
# @param from [Integer] Specifies lower limit.
# @param to [Integer] Specifies upper limit.
# @return [Integer]
#
# @example
# Faker::Invoice.amount_between #=> 0
# Faker::Invoice.amount_between(from: 0, to: 10) #=> 4.33
#
# @faker.version 1.9.0
def amount_between(from: 0, to: 0)
Faker::Base.rand_in_range(from, to).round(2)
end
##
# Produces a random valid reference according to the International bank slip reference https://en.wikipedia.org/wiki/Creditor_Reference
#
# @param ref [String] Specifies reference base.
# @return [String]
#
# @example
# Faker::Invoice.creditor_reference #=> "RF34118592570724925498"
#
# @faker.version 1.9.0
def creditor_reference(ref: '')
ref = reference if ref.empty?
"RF#{iban_checksum('RF', ref)}#{ref}"
end
##
# Produces a random valid reference.
#
# @param ref [String] Specifies reference base.
# @return [String]
#
# @example
# Faker::Invoice.reference #=> "45656646957845"
#
# @faker.version 1.9.0
def reference(ref: '')
pattern = fetch('invoice.reference.pattern')
ref = Base.regexify(/#{pattern}/) if ref.empty?
# If reference contains reserved '#' characters we need to calculate check_digits as well
check_digit_match = ref.match(/#+/)
if check_digit_match
# Get the method for selected language
check_digit_method = fetch('invoice.reference.check_digit_method')
# Calculate the check digit with matching method name
# Trim all '#' from the reference before calculating that
check_digit = send(check_digit_method, ref.tr('#', ''))
# Make sure that our check digit is as long as all of the '###' we found
check_digit = check_digit.to_s.rjust(check_digit_match[0].length, '0')
# Replace all of the
ref = ref.sub(check_digit_match[0], check_digit)
end
ref
end
private
# Calculates the mandatory checksum in 3rd and 4th characters in IBAN format
# source: https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
def iban_checksum(country_code, account)
# Converts letters to numbers according the iban rules, A=10..Z=35
account_to_number = "#{account}#{country_code}00".upcase.chars.map do |d|
d =~ /[A-Z]/ ? (d.ord - 55).to_s : d
end.join.to_i
# This is answer to (iban_to_num + checksum) % 97 == 1
checksum = (1 - account_to_number) % 97
# Use leftpad to make the size always to 2
checksum.to_s.rjust(2, '0')
end
# 731 Method
# Source: https://wiki.xmldation.com/support/fk/finnish_reference_number
def method_731(base)
weighted_sum = calculate_weighted_sum(base, [7, 3, 1])
mod10_remainder(weighted_sum)
end
# Norsk Modulus 10 - KIDMOD10
def kidmod10(base)
weighted_sum = calculate_weighted_sum(base, [1, 2])
mod10_remainder(weighted_sum)
end
# Calculates weighted sum
#
# For example with 12345678, [1,2]
# Ref.num. 1 2 3 4 5 6 7 8
# Multipl. 1 2 1 2 1 2 1 2
# Total 1+ 4+ 3+ 8+ 5+1+2+ 7+1+6 = 38
def calculate_weighted_sum(base, weight_factors)
base.to_s.reverse.each_char.with_index.map do |digit, index|
digit.to_i * weight_factors.at(index % weight_factors.length)
end.reduce(:+) # reduce(:+) = sum() but with better ruby version support
end
# MOD-10 - remainder
def mod10_remainder(number)
-number % 10
end
end
end
end
|