lib/article_units_lib.rb
Rama master · réplica de lectura del repositorio original.
class ArticleUnitsLib
DEFAULT_PIECE_UNIT_CODES = %w[PTN STC XCU XCN XSH X43 XST XOK XVA XBX XBH XBE XCX XBJ XUN XOS XDH XBA XFI XBO XBQ XFB XFT XJR XGR XOW X8B XCV XWA XEI XJT XGY XJY XBD XCR XAI XPA XBK XBI XOV XNT XPK XPC XPX X5M XPR XEC X6H X44 XBR XCW XBT XSA XBM XSX XDN XAE XSC XLU X5L XPP XPU XBG XP2 XCK XPT XGI XTU]
DEFAULT_METRIC_SCALAR_UNIT_CODES = %w[KGM HGM DJ GRM LTR DLT CLT MLT]
DEFAULT_IMPERIAL_SCALAR_UNIT_CODES = %w[LBR ONZ GLL QTI PTI]
@un_ece_20_units = YAML.safe_load(ERB.new(File.read(File.expand_path(
'config/units-of-measure/un-ece-20-remastered.yml', Rails.root
))).result)
@un_ece_21_units = YAML.safe_load(ERB.new(File.read(File.expand_path('config/units-of-measure/un-ece-21.yml',
Rails.root))).result)
def self.untranslated_units
return @untranslated_units unless @untranslated_units.nil?
options = {}
@un_ece_20_units.each do |unit|
code = unit['CommonCode']
base_unit = unit['conversion']['base_units'].nil? ? nil : unit['conversion']['base_units'][0]
options[code] =
{ name: unit['Name'], description: unit['Description'], baseUnit: base_unit,
conversionFactor: unit['conversion']['factor'], symbol: unit['Symbol'] }
end
@un_ece_21_units.each do |unit|
code = 'X' + unit['Code']
name = unit['Name']
name[0] = name[0].downcase
options[code] =
{ name: name, description: unit['Description'], baseUnit: nil, conversionFactor: nil, symbol: unit['Symbol'] }
end
options.each do |code, option|
option[:translation_available] = !ArticleUnitsLib.get_translated_name_for_code(code, default_nil: true).nil?
end
@untranslated_units = options
end
def self.unit_translations
@unit_translations = {} if @unit_translations.nil?
unit_translations_cached_in_current_locale = @unit_translations[I18n.locale]
return unit_translations_cached_in_current_locale unless unit_translations_cached_in_current_locale.nil?
@unit_translations[I18n.locale] = YAML.safe_load(ERB.new(File.read(File.expand_path(
"config/units-of-measure/locales/unece_#{I18n.locale}.yml", Rails.root
))).result) || {}
end
def self.units
@units = {} if @units.nil?
units_cached_in_current_locale = @units[I18n.locale]
return units_cached_in_current_locale unless units_cached_in_current_locale.nil?
@units[I18n.locale] = untranslated_units.to_h do |code, untranslated_unit|
translated_name = ArticleUnitsLib.get_translated_name_for_code(code, default_nil: true)
unit = untranslated_unit.clone
unit[:name] = translated_name || unit[:name]
unit[:untranslated] = translated_name.nil?
unit[:symbol] = ArticleUnitsLib.get_translated_symbol_for_code(code)
unit[:aliases] = ArticleUnitsLib.get_translated_aliases_for_code(code)
[code, unit]
end
end
def self.unit_is_si_convertible(code)
!units[code]&.dig(:conversionFactor).nil?
end
def self.human_readable_unit(unit_code)
unit = units.to_h[unit_code]
unit[:symbol] || unit[:name]
end
def self.get_translated_name_for_code(code, default_nil: false)
return nil if code.blank?
unit_translations&.dig('unece_units', code, 'name') || (default_nil ? nil : untranslated_units[code][:name])
end
def self.get_translated_symbol_for_code(code)
return nil if code.blank?
unit_translations&.dig('unece_units', code, 'symbols', 0) || untranslated_units[code][:symbol]
end
def self.get_translated_aliases_for_code(code)
return nil if code.blank?
unit_translations&.dig('unece_units', code, 'aliases')
end
def self.get_code_for_unit_name(name)
return nil if name.blank?
translation = unit_translations&.dig('unece_units')&.find do |_code, translations|
translations['name'] == name
end
return translation[0] unless translation.nil?
matching_unit = units.find do |_code, unit|
unit[:name] == name
end
matching_unit[0]
end
def self.convert_old_unit(old_compound_unit_str, unit_quantity)
return nil if old_compound_unit_str.nil?
md = old_compound_unit_str.match(/([0-9]*)x(.*)/)
old_compound_unit_str = md[2] if !md.nil? && md[1].to_f == unit_quantity
md = old_compound_unit_str.match(%r{^\s*([0-9][0-9,./]*)?\s*([A-Za-z\u00C0-\u017F.]+)\s*$})
return nil if md.nil?
unit = get_unit_from_old_str(md[2])
return nil if unit.nil?
quantity = get_quantity_from_old_str(md[1])
if quantity == 1 && unit_quantity == 1
{
supplier_order_unit: unit,
first_ratio: nil,
group_order_granularity: 1.0,
group_order_unit: unit
}
else
supplier_order_unit = unit.starts_with?('X') && unit != 'XPK' ? 'XPK' : 'XPP'
{
supplier_order_unit: supplier_order_unit,
first_ratio: {
quantity: quantity * unit_quantity,
unit: unit
},
group_order_granularity: unit_quantity > 1 ? quantity : 1.0,
group_order_unit: unit_quantity > 1 ? unit : supplier_order_unit
}
end
end
def self.get_quantity_from_old_str(quantity_str)
return 1 if quantity_str.nil?
quantity_str = quantity_str
.gsub(',', '.')
.gsub(' ', '')
division_parts = quantity_str.split('/').map(&:to_f)
if division_parts.length == 2
division_parts[0] / division_parts[1]
else
quantity_str.to_f
end
end
def self.get_unit_from_old_str(old_unit_str)
unit_str = old_unit_str.strip.downcase
units = ArticleUnitsLib.untranslated_units
.sort { |a, b| sort_by_translation_state(a[1], b[1]) }
matching_unit_arr = units.select { |key, unit| matches_unit(key, unit, unit_str) }
.to_a
return nil if matching_unit_arr.empty?
matching_unit_arr[0][0]
end
def self.sort_by_translation_state(unit_a, unit_b)
return -1 if unit_a[:translation_available] && !unit_b[:translation_available]
return 1 if unit_b[:translation_available] && !unit_a[:translation_available]
0
end
def self.matches_unit(unit_code, unit, unit_str)
return true if unit[:symbol] == unit_str
translation_data = unit_translations&.dig('unece_units', unit_code)
return true if translation_data&.dig('symbols')&.include?(unit_str)
name = translation_data&.dig('name')&.downcase
return true if !name.nil? && name == unit_str
aliases = translation_data&.dig('aliases')&.map { |a| a.strip.downcase }
!aliases.nil? && aliases.any? { |a| a == unit_str || "#{a}." == unit_str }
end
end