Module: ONIX::ProductSuppliesExtractor

Included in:
ONIX21::Product, Product
Defined in:
lib/onix/product.rb

Overview

flattened supplies extractor

Instance Method Summary collapse

Instance Method Details

#add_ending_period(supply, global_supply) ⇒ Object



211
212
213
214
215
216
# File 'lib/onix/product.rb', line 211

def add_ending_period(supply, global_supply)
  missing_supply = global_supply.dup
  missing_supply[:from_date] = supply[:until_date] + 1

  [supply, missing_supply]
end

#add_missing_periods(supplies, global_supply) ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/onix/product.rb', line 183

def add_missing_periods(supplies, global_supply)
  new_supplies = []

  supplies.each.with_index do |supply, index|
    new_supplies << global_supply.dup.tap{ |start_sup| start_sup[:until_date] = supply[:from_date] - 1 } if index == 0

    if index > 0 && index != supplies.length
      new_supplies << global_supply.dup.tap do |missing_supply|
        missing_supply[:from_date] = supplies[index - 1][:until_date] + 1
        missing_supply[:until_date] = supply[:from_date] - 1
      end
    end

    new_supplies << supply

    new_supplies << global_supply.dup.tap{ |end_sup| end_sup[:from_date] = supply[:until_date] + 1 } if index == supplies.length - 1
  end

  new_supplies
end

#add_starting_period(supply, global_supply) ⇒ Object



204
205
206
207
208
209
# File 'lib/onix/product.rb', line 204

def add_starting_period(supply, global_supply)
  missing_supply = global_supply.dup
  missing_supply[:until_date] = supply[:from_date] - 1

  [missing_supply, supply]
end

#at_time_price_amount_for(time, currency, country = nil) ⇒ Object

:category: High level price amount for given currency and country at time



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/onix/product.rb', line 254

def at_time_price_amount_for(time,currency,country=nil)
  sups=self.supplies_with_default_tax.select { |p| p[:currency]==currency }
  if country
    sups=sups.select{|p| p[:territory].include?(country)}
  end
  if sups.length > 0
    # exclusive
    sup=sups.first[:prices].select { |p|
      (!p[:from_date] or p[:from_date].to_date <= time.to_date) and
          (!p[:until_date] or p[:until_date].to_date > time.to_date)
    }.first

    if sup
      sup[:amount]
    else
      # or inclusive
      sup=sups.first[:prices].select { |p|
        (!p[:from_date] or p[:from_date].to_date <= time.to_date) and
            (!p[:until_date] or p[:until_date].to_date >= time.to_date)
      }.first

      if sup
        sup[:amount]
      else
        nil
      end
    end

  else
    nil
  end
end

#current_price_amount_for(currency, country = nil) ⇒ Object

:category: High level current price amount for given currency and country



289
290
291
# File 'lib/onix/product.rb', line 289

def current_price_amount_for(currency,country=nil)
  at_time_price_amount_for(Time.now,currency,country)
end

#prices_with_periods(supplies, global_supply) ⇒ Object

add missing periods when they can be guessed



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/onix/product.rb', line 165

def prices_with_periods(supplies, global_supply)
  complete_supplies = supplies.select{ |supply| supply[:from_date] && supply[:until_date] }.sort_by { |supply| supply[:from_date] }
  missing_start_period_supplies = supplies.select{ |supply| supply[:from_date] && !supply[:until_date] }.sort_by { |supply| supply[:from_date] }
  missing_end_period_supplies = supplies.select{ |supply| !supply[:from_date] && supply[:until_date] }.sort_by { |supply| supply[:until_date] }

  return [global_supply] if [complete_supplies, missing_start_period_supplies, missing_end_period_supplies].all? {|supply| supply.empty? }

  return self.add_missing_periods(complete_supplies, global_supply) unless complete_supplies.empty?

  without_start = missing_start_period_supplies.length == 1 && complete_supplies.empty? && missing_end_period_supplies.empty?
  without_end = missing_end_period_supplies.length == 1 && complete_supplies.empty? && missing_start_period_supplies.empty?

  return self.add_starting_period(missing_start_period_supplies.first, global_supply) if without_start
  return self.add_ending_period(missing_end_period_supplies.first, global_supply) if without_end

  [global_supply]
end

#supplies(keep_all_prices_dates = false) ⇒ Object

:category: High level flattened supplies with prices

supplies is a hash symbol array in the form :

[{:available=>bool,
  :availability_date=>date,
  :including_tax=>bool,
  :currency=>string,
  :territory=>string,
  :suppliers=>[Supplier,...],
  :prices=>[{:amount=>int,
             :from_date=>date,
             :until_date=>date,
             :tax=>{:amount=>int, :rate_percent=>float}}]}]


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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/onix/product.rb', line 36

def supplies(keep_all_prices_dates=false)
  supplies=[]

  # add territories if missing
  if self.product_supplies
    self.product_supplies.each do |ps|
      ps.supply_details.each do |sd|
        sd.prices.each do |p|
          supply={}
          supply[:suppliers]=sd.suppliers
          supply[:available]=sd.available?
          supply[:availability_date]=sd.availability_date

          unless supply[:availability_date]
              if ps.availability_date
                supply[:availability_date]=ps.market_publishing_detail.availability_date
              end
          end
          supply[:price]=p.amount
          supply[:qualifier]=p.qualifier.human if p.qualifier
          supply[:including_tax]=p.including_tax?
          if !p.territory or p.territory.countries.length==0
            supply[:territory]=[]
            supply[:territory]=ps.countries

            if supply[:territory].length==0
              if @publishing_detail
                supply[:territory]=self.countries_rights
              end
            end
          else
            supply[:territory]=p.territory.countries
          end
          supply[:from_date]=p.from_date
          supply[:until_date]=p.until_date
          supply[:currency]=p.currency
          supply[:tax]=p.tax

          unless supply[:availability_date]
            if @publishing_detail
              supply[:availability_date]=@publishing_detail.publication_date
            end
          end

          supplies << supply
        end
      end
    end
  end

  grouped_supplies={}
  supplies.each do |supply|
    pr_key="#{supply[:available]}_#{supply[:including_tax]}_#{supply[:currency]}_#{supply[:territory].join('_')}"
    grouped_supplies[pr_key]||=[]
    grouped_supplies[pr_key] << supply
  end

  nb_suppliers = supplies.map{|s| s[:suppliers][0].name}.uniq.length
  # render prices sequentially with dates
  grouped_supplies.each do |ksup, supply|
    if supply.length > 1
      global_price=supply.select{|p| not p[:from_date] and not p[:until_date]}
      global_price=global_price.first

      if global_price
        if nb_suppliers > 1
          grouped_supplies[ksup] += self.prices_with_periods(supply, global_price)
        else
          grouped_supplies[ksup] = self.prices_with_periods(supply, global_price)
        end
        grouped_supplies[ksup].uniq!
      else
        # remove explicit from date
        explicit_from=supply.select{|p| p[:from_date] and not supply.select{|sp| sp[:until_date] and sp[:until_date]<=p[:from_date]}.first}.first
        if explicit_from
          explicit_from[:from_date]=nil unless keep_all_prices_dates
        end
      end


    else
      supply.each do |s|
        if s[:from_date] and s[:availability_date] and s[:from_date] >= s[:availability_date]
          s[:availability_date]=s[:from_date]
        end
        s[:from_date]=nil unless keep_all_prices_dates

      end
    end
  end

  # merge by territories
  grouped_territories_supplies={}
  grouped_supplies.each do |ksup,supply|
    fsupply=supply.first
    pr_key="#{fsupply[:available]}_#{fsupply[:including_tax]}_#{fsupply[:currency]}"
    supply.each do |s|
      pr_key+="_#{s[:price]}_#{s[:from_date]}_#{s[:until_date]}"
    end
    grouped_territories_supplies[pr_key]||=[]
    grouped_territories_supplies[pr_key] << supply
  end

  supplies=[]

  grouped_territories_supplies.each do |ksup,supply|
    fsupply=supply.first.first
    supplies << {:including_tax=>fsupply[:including_tax],:currency=>fsupply[:currency],
                 :territory=>supply.map{|fs| fs.map{|s| s[:territory]}}.flatten.uniq,
                 :available=>fsupply[:available],
                 :availability_date=>fsupply[:availability_date],
                 :suppliers=>fsupply[:suppliers],
                 :prices=>supply.first.map{|s|

                   s[:amount]=s[:price]
                   s.delete(:price)
                   s.delete(:available)
                   s.delete(:currency)
                   s.delete(:availability_date)
                   s.delete(:including_tax)
                   s.delete(:territory)
                   s
                 }}
  end

  supplies
end

#supplies_excluding_taxObject

:category: High level flattened supplies only excluding taxes



226
227
228
# File 'lib/onix/product.rb', line 226

def supplies_excluding_tax
  self.supplies.select{|p| not p[:including_tax]}
end

#supplies_for_country(country, currency = nil) ⇒ Object

:category: High level flattened supplies for country



238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/onix/product.rb', line 238

def supplies_for_country(country,currency=nil)
  country_supplies=self.supplies
  if currency
    country_supplies=country_supplies.select{|s| s[:currency]==currency}
  end
  country_supplies.select{|s|
    if s[:territory].include?(country)
      true
    else
      false
    end
  }
end

#supplies_including_taxObject

:category: High level flattened supplies only including taxes



220
221
222
# File 'lib/onix/product.rb', line 220

def supplies_including_tax
  self.supplies.select{|p| p[:including_tax]}
end

#supplies_with_default_taxObject

:category: High level flattened supplies with default tax (excluding tax for US and CA, including otherwise)



232
233
234
# File 'lib/onix/product.rb', line 232

def supplies_with_default_tax
  self.supplies_including_tax + self.supplies_excluding_tax.select{|s| ["CAD","USD"].include?(s[:currency])}
end