Class: Supplier

Inherits:
ApplicationRecord show all
Includes:
CustomFields, ExtendableEnum, MarkAsDeletedWithName
Defined in:
app/models/supplier.rb

Class Attribute Summary collapse

Attributes included from CustomFields

#custom_fields

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.remote_order_formattersObject

Returns the value of attribute remote_order_formatters.



40
41
42
# File 'app/models/supplier.rb', line 40

def remote_order_formatters
  @remote_order_formatters
end

Class Method Details

.ransackable_associations(_auth_object = nil) ⇒ Object



59
60
61
# File 'app/models/supplier.rb', line 59

def self.ransackable_associations(_auth_object = nil)
  %w[articles stock_articles orders]
end

.ransackable_attributes(_auth_object = nil) ⇒ Object



55
56
57
# File 'app/models/supplier.rb', line 55

def self.ransackable_attributes(_auth_object = nil)
  %w[id name]
end

.register_remote_order_method(method, formatter_class) ⇒ Object

Register a remote order method with its formatter (to be used by plugins)

Parameters:

  • method (Symbol)

    The key for the remote order method

  • formatter_class (Class)

    The class that will format the order for remote ordering



50
51
52
53
# File 'app/models/supplier.rb', line 50

def self.register_remote_order_method(method, formatter_class)
  add_remote_order_method_value(method)
  @remote_order_formatters[method] = formatter_class
end

Instance Method Details

#deleted?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'app/models/supplier.rb', line 99

def deleted?
  deleted_at.present?
end

#foodsoft_file_attrs_to_article(foodsoft_file_attrs) ⇒ Object (protected)



183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'app/models/supplier.rb', line 183

def foodsoft_file_attrs_to_article(foodsoft_file_attrs)
  foodsoft_file_attrs = foodsoft_file_attrs.dup
  foodsoft_file_attrs[:article_category] = .find_match(foodsoft_file_attrs[:article_category])
  foodsoft_file_attrs[:tax] ||= FoodsoftConfig[:tax_default]
  foodsoft_file_attrs[:article_unit_ratios] = foodsoft_file_attrs[:article_unit_ratios].map do |ratio_hash|
    ArticleUnitRatio.new(ratio_hash)
  end
  new_article = articles.build
  new_article_version = new_article.article_versions.build(foodsoft_file_attrs)
  new_article.article_versions << new_article_version
  new_article.latest_article_version = new_article_version

  new_article
end

#has_tolerance?Boolean

Returns Whether there are articles that would use tolerance.

Returns:

  • (Boolean)

    Whether there are articles that would use tolerance



112
113
114
# File 'app/models/supplier.rb', line 112

def has_tolerance?
  articles.with_latest_versions_and_categories.any? { |article| article.latest_article_version.uses_tolerance? }
end

#mark_as_deletedObject



103
104
105
106
107
108
109
# File 'app/models/supplier.rb', line 103

def mark_as_deleted
  transaction do
    super
    update_column :iban, nil
    articles.each(&:mark_as_deleted)
  end
end

#parse_import_data(data, options = {}) ⇒ Object (protected)



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'app/models/supplier.rb', line 145

def parse_import_data(data, options = {})
  all_order_numbers = []
  updated_article_pairs = []
  outlisted_articles = []
  new_articles = []

  data[:articles].each do |new_attrs|
    undeleted_articles = articles.includes(:latest_article_version).undeleted
    article = if new_attrs[:id]
                undeleted_articles.where(id: new_attrs[:id]).first
              else
                undeleted_articles.where(article_versions: { order_number: new_attrs[:order_number] }).first
              end
    new_article = foodsoft_file_attrs_to_article(new_attrs)

    if new_attrs[:availability] || !(options[:delete_unavailable])
      if article.nil?
        new_articles << new_article
      else
        unequal_attributes = article.unequal_attributes(new_article, options.slice(:convert_units))
        unless unequal_attributes.empty?
          article.latest_article_version.article_unit_ratios.target.clear unless unequal_attributes[:article_unit_ratios_attributes].nil?
          article.latest_article_version.attributes = unequal_attributes
          duped_ratios = article.latest_article_version.article_unit_ratios.map(&:dup)
          article.latest_article_version.article_unit_ratios.target.clear
          article.latest_article_version.article_unit_ratios.target.push(*duped_ratios)
          updated_article_pairs << [article, unequal_attributes]
        end
      end
    elsif article.present?
      outlisted_articles << article
    end
    all_order_numbers << article.order_number if article
  end
  outlisted_articles += articles.includes(:latest_article_version).undeleted.where.not(article_versions: { order_number: all_order_numbers + [nil] }) if options[:outlist_absent]
  [updated_article_pairs, outlisted_articles, new_articles]
end

#read_from_remote(search_params = {}) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'app/models/supplier.rb', line 78

def read_from_remote(search_params = {})
  url = URI(supplier_remote_source)
  case url.scheme
  when 'http', 'https'
    read_from_http(url, search_params)
  when 'ftp'
    read_from_ftp(url)
  else
    raise "Unsupported protocol: #{url.scheme}"
  end
end

#remote_order_formatterObject



43
44
45
# File 'app/models/supplier.rb', line 43

def remote_order_formatter
  self.class.remote_order_formatters[remote_order_method]
end

#shared_sync_method=(value) ⇒ Object



125
126
127
128
129
130
131
# File 'app/models/supplier.rb', line 125

def shared_sync_method=(value)
  if value.blank?
    self[:shared_sync_method] = nil
  else
    super
  end
end

#supplier_remote_source=(value) ⇒ Object

TODO: Maybe use the ‘nilify_blanks` gem instead of the following two methods? (see github.com/foodcoopsat/foodsoft_hackathon/issues/93):



117
118
119
120
121
122
123
# File 'app/models/supplier.rb', line 117

def supplier_remote_source=(value)
  if value.blank?
    self[:supplier_remote_source] = nil
  else
    super
  end
end

#sync_from_file(file, options = {}) ⇒ Object

Synchronise articles with spreadsheet.

Parameters:

  • file (File)

    Spreadsheet file to parse

  • options (Hash) (defaults to: {})

    Options passed to FoodsoftFile.parse except when listed here.

Options Hash (options):

  • :outlist_absent (Boolean)

    Set to true to remove articles not in spreadsheet.

  • :convert_units (Boolean)

    Omit or set to true to keep current units, recomputing unit quantity and price.



69
70
71
72
73
74
75
76
# File 'app/models/supplier.rb', line 69

def sync_from_file(file, options = {})
  data = FoodsoftFile.parse(file, options)
  data.each do |new_attrs|
    new_article = foodsoft_file_attrs_to_article(new_attrs.dup)
    new_attrs[:price] = new_attrs[:price].to_d / new_article.convert_quantity(1, new_article.price_unit, new_article.supplier_order_unit)
  end
  parse_import_data({ articles: data }, options) + [data]
end

#sync_from_remote(options = {}) ⇒ Object



90
91
92
93
94
95
96
97
# File 'app/models/supplier.rb', line 90

def sync_from_remote(options = {})
  data = read_from_remote(options[:search_params])
  updated_article_pairs, outlisted_articles, new_articles = parse_import_data(data, options)

  available = shared_sync_method == 'all_available'
  new_articles.each { |new_article| new_article.availability = available }
  [updated_article_pairs, outlisted_articles, new_articles, data]
end

#uniqueness_of_nameObject (protected)

Make sure, the name is uniq, add usefull message if uniq group is already deleted



136
137
138
139
140
141
142
143
# File 'app/models/supplier.rb', line 136

def uniqueness_of_name
  supplier = Supplier.where(name: name)
  supplier = supplier.where.not(id: id) unless new_record?
  return unless supplier.exists?

  message = supplier.first.deleted? ? :taken_with_deleted : :taken
  errors.add :name, message
end