• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

foodcoops / foodsoft / 21521827700

30 Jan 2026 03:53PM UTC coverage: 42.78% (-24.3%) from 67.127%
21521827700

Pull #1269

github

lentschi
Remove GitHub deploy workflow
Pull Request #1269: Remove GitHub deploy workflow

3087 of 7216 relevant lines covered (42.78%)

11.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.45
/lib/article_units_lib.rb
1
class ArticleUnitsLib
1✔
2
  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]
1✔
3
  DEFAULT_METRIC_SCALAR_UNIT_CODES = %w[KGM HGM DJ GRM LTR DLT CLT MLT]
1✔
4
  DEFAULT_IMPERIAL_SCALAR_UNIT_CODES = %w[LBR ONZ GLL QTI PTI]
1✔
5

6
  @un_ece_20_units = YAML.safe_load(ERB.new(File.read(File.expand_path(
1✔
7
                                                        'config/units-of-measure/un-ece-20-remastered.yml', Rails.root
8
                                                      ))).result)
9
  @un_ece_21_units = YAML.safe_load(ERB.new(File.read(File.expand_path('config/units-of-measure/un-ece-21.yml',
1✔
10
                                                                       Rails.root))).result)
11

12
  def self.untranslated_units
1✔
13
    return @untranslated_units unless @untranslated_units.nil?
2,383✔
14

15
    options = {}
1✔
16

17
    @un_ece_20_units.each do |unit|
1✔
18
      code = unit['CommonCode']
2,117✔
19
      base_unit = unit['conversion']['base_units'].nil? ? nil : unit['conversion']['base_units'][0]
2,117✔
20
      options[code] =
2,117✔
21
        { name: unit['Name'], description: unit['Description'], baseUnit: base_unit,
22
          conversionFactor: unit['conversion']['factor'], symbol: unit['Symbol'] }
23
    end
24

25
    @un_ece_21_units.each do |unit|
1✔
26
      code = 'X' + unit['Code']
382✔
27
      name = unit['Name']
382✔
28
      name[0] = name[0].downcase
382✔
29

30
      options[code] =
382✔
31
        { name: name, description: unit['Description'], baseUnit: nil, conversionFactor: nil, symbol: unit['Symbol'] }
32
    end
33

34
    options.each do |code, option|
1✔
35
      option[:translation_available] = !ArticleUnitsLib.get_translated_name_for_code(code, default_nil: true).nil?
2,499✔
36
    end
37

38
    @untranslated_units = options
1✔
39
  end
40

41
  def self.unit_translations
1✔
42
    @unit_translations = {} if @unit_translations.nil?
9,996✔
43
    unit_translations_cached_in_current_locale = @unit_translations[I18n.locale]
9,996✔
44
    return unit_translations_cached_in_current_locale unless unit_translations_cached_in_current_locale.nil?
9,996✔
45

46
    @unit_translations[I18n.locale] = YAML.safe_load(ERB.new(File.read(File.expand_path(
1✔
47
                                                                         "config/units-of-measure/locales/unece_#{I18n.locale}.yml", Rails.root
48
                                                                       ))).result) || {}
49
  end
50

51
  def self.units
1✔
52
    @units = {} if @units.nil?
2✔
53
    units_cached_in_current_locale = @units[I18n.locale]
2✔
54
    return units_cached_in_current_locale unless units_cached_in_current_locale.nil?
2✔
55

56
    @units[I18n.locale] = untranslated_units.to_h do |code, untranslated_unit|
1✔
57
      translated_name = ArticleUnitsLib.get_translated_name_for_code(code, default_nil: true)
2,499✔
58
      unit = untranslated_unit.clone
2,499✔
59
      unit[:name] = translated_name || unit[:name]
2,499✔
60
      unit[:untranslated] = translated_name.nil?
2,499✔
61
      unit[:symbol] = ArticleUnitsLib.get_translated_symbol_for_code(code)
2,499✔
62
      unit[:aliases] = ArticleUnitsLib.get_translated_aliases_for_code(code)
2,499✔
63

64
      [code, unit]
2,499✔
65
    end
66
  end
67

68
  def self.unit_is_si_convertible(code)
1✔
69
    !units[code]&.dig(:conversionFactor).nil?
2✔
70
  end
71

72
  def self.human_readable_unit(unit_code)
1✔
73
    unit = units.to_h[unit_code]
×
74
    unit[:symbol] || unit[:name]
×
75
  end
76

77
  def self.get_translated_name_for_code(code, default_nil: false)
1✔
78
    return nil if code.blank?
4,998✔
79

80
    unit_translations&.dig('unece_units', code, 'name') || (default_nil ? nil : untranslated_units[code][:name])
4,998✔
81
  end
82

83
  def self.get_translated_symbol_for_code(code)
1✔
84
    return nil if code.blank?
2,499✔
85

86
    unit_translations&.dig('unece_units', code, 'symbols', 0) || untranslated_units[code][:symbol]
2,499✔
87
  end
88

89
  def self.get_translated_aliases_for_code(code)
1✔
90
    return nil if code.blank?
2,499✔
91

92
    unit_translations&.dig('unece_units', code, 'aliases')
2,499✔
93
  end
94

95
  def self.get_code_for_unit_name(name)
1✔
96
    return nil if name.blank?
×
97

98
    translation = unit_translations&.dig('unece_units')&.find do |_code, translations|
×
99
      translations['name'] == name
×
100
    end
101

102
    return translation[0] unless translation.nil?
×
103

104
    matching_unit = units.find do |_code, unit|
×
105
      unit[:name] == name
×
106
    end
107

108
    matching_unit[0]
×
109
  end
110

111
  def self.convert_old_unit(old_compound_unit_str, unit_quantity)
1✔
112
    return nil if old_compound_unit_str.nil?
×
113

114
    md = old_compound_unit_str.match(/([0-9]*)x(.*)/)
×
115
    old_compound_unit_str = md[2] if !md.nil? && md[1].to_f == unit_quantity
×
116

117
    md = old_compound_unit_str.match(%r{^\s*([0-9][0-9,./]*)?\s*([A-Za-z\u00C0-\u017F.]+)\s*$})
×
118
    return nil if md.nil?
×
119

120
    unit = get_unit_from_old_str(md[2])
×
121
    return nil if unit.nil?
×
122

123
    quantity = get_quantity_from_old_str(md[1])
×
124

125
    if quantity == 1 && unit_quantity == 1
×
126
      {
127
        supplier_order_unit: unit,
×
128
        first_ratio: nil,
129
        group_order_granularity: 1.0,
130
        group_order_unit: unit
131
      }
132
    else
133
      supplier_order_unit = unit.starts_with?('X') && unit != 'XPK' ? 'XPK' : 'XPP'
×
134
      {
135
        supplier_order_unit: supplier_order_unit,
×
136
        first_ratio: {
137
          quantity: quantity * unit_quantity,
138
          unit: unit
139
        },
140
        group_order_granularity: unit_quantity > 1 ? quantity : 1.0,
×
141
        group_order_unit: unit_quantity > 1 ? unit : supplier_order_unit
×
142
      }
143
    end
144
  end
145

146
  def self.get_quantity_from_old_str(quantity_str)
1✔
147
    return 1 if quantity_str.nil?
×
148

149
    quantity_str = quantity_str
×
150
                   .gsub(',', '.')
151
                   .gsub(' ', '')
152

153
    division_parts = quantity_str.split('/').map(&:to_f)
×
154

155
    if division_parts.length == 2
×
156
      division_parts[0] / division_parts[1]
×
157
    else
158
      quantity_str.to_f
×
159
    end
160
  end
161

162
  def self.get_unit_from_old_str(old_unit_str)
1✔
163
    unit_str = old_unit_str.strip.downcase
×
164
    units = ArticleUnitsLib.untranslated_units
×
165
                           .sort { |a, b| sort_by_translation_state(a[1], b[1]) }
×
166
    matching_unit_arr = units.select { |key, unit| matches_unit(key, unit, unit_str) }
×
167
                             .to_a
168
    return nil if matching_unit_arr.empty?
×
169

170
    matching_unit_arr[0][0]
×
171
  end
172

173
  def self.sort_by_translation_state(unit_a, unit_b)
1✔
174
    return -1 if unit_a[:translation_available] && !unit_b[:translation_available]
×
175
    return 1 if unit_b[:translation_available] && !unit_a[:translation_available]
×
176

177
    0
×
178
  end
179

180
  def self.matches_unit(unit_code, unit, unit_str)
1✔
181
    return true if unit[:symbol] == unit_str
×
182

183
    translation_data = unit_translations&.dig('unece_units', unit_code)
×
184

185
    return true if translation_data&.dig('symbols')&.include?(unit_str)
×
186

187
    name = translation_data&.dig('name')&.downcase
×
188
    return true if !name.nil? && name == unit_str
×
189

190
    aliases = translation_data&.dig('aliases')&.map { |a| a.strip.downcase }
×
191
    !aliases.nil? && aliases.any? { |a| a == unit_str || "#{a}." == unit_str }
×
192
  end
193
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc