Class: Ekylibre::BackupExchanger::Backup

Inherits:
Hash
  • Object
show all
Defined in:
app/exchangers/ekylibre/backup_exchanger.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Backup

Returns a new instance of Backup.


76
77
78
79
80
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 76

def initialize(*args)
  super(*args)
  @matchings = {}.with_indifferent_access
  @indexes = {}.with_indifferent_access
end

Instance Attribute Details

#matchingsObject (readonly)

Returns the value of attribute matchings


38
39
40
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 38

def matchings
  @matchings
end

Class Method Details

.load(company) ⇒ Object


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
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 40

def self.load(company)
  # x = schema.select do |table, columns|
  #   y = columns.keys.delete_if{|c| [:creator_id, :updater_id, :company_id].include?(c)}.detect{|c| c.to_s =~ /\_id$/}
  #   y
  # end.keys
  # # Root models: (models.map{|m| m.to_s.pluralize.to_sym} - x)
  backup = new
  company.children.each do |rows|
    model = rows.attr(:model).to_sym
    table = model.to_s.pluralize.to_sym
    backup[model] = []
    rows.children.each do |row|
      backup[model] << row.attributes.each_with_object({}) do |pair, hash|
        attribute = pair.first.to_sym
        value = pair.second.to_s
        type = schema[table][attribute][:type].to_sym
        if type == :boolean
          value = (value == 'true')
        elsif type == :integer
          value = (value.blank? ? nil : value.to_i)
        elsif type == :decimal
          value = (value.blank? ? nil : value.to_d)
        elsif type == :date
          value = (value.blank? ? nil : value.to_date)
        elsif type == :datetime
          value = (value.blank? ? nil : value.to_datetime)
        end
        value = nil if value.blank? && type != :boolean
        hash[attribute] = value unless [:company_id].include?(attribute)
        hash
      end.to_struct
    end
  end
  backup
end

.modelsObject


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
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 7

def models
  %i[account account_balance area asset asset_depreciation
     bank_statement cash cash_transfer contact cultivation
     custom_field custom_field_choice custom_field_datum delay
     department deposit deposit_line district document
     document_template entity entity_category entity_link
     entity_link_nature entity_nature establishment event
     event_nature financial_year incoming_delivery
     incoming_delivery_line incoming_delivery_mode incoming_payment
     incoming_payment_mode incoming_payment_use inventory
     inventory_line journal journal_entry journal_entry_line
     land_parcel land_parcel_group land_parcel_kinship listing
     listing_node listing_node_item mandate observation
     operation operation_line operation_nature operation_use
     outgoing_delivery outgoing_delivery_line outgoing_delivery_mode
     outgoing_payment outgoing_payment_mode outgoing_payment_use
     preference price product product_category product_component
     production_chain production_chain_conveyor
     production_chain_work_center production_chain_work_center_use
     profession purchase purchase_line purchase_nature role
     sale sale_line sale_nature sequence stock stock_move
     stock_transfer subscription subscription_nature tax
     tax_declaration tool tracking tracking_state transfer
     transport unit user warehouse]
end

.schemaObject


33
34
35
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 33

def schema
  @schema ||= YAML.load_file(Pathname.new(__FILE__).dirname.join('backup', 'schema-0.4.yml')).deep_symbolize_keys.freeze
end

Instance Method Details

#browse_and_match(backup_model) ⇒ Object


203
204
205
206
207
208
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 203

def browse_and_match(backup_model)
  @matchings[backup_model] ||= {}
  self[backup_model].each do |item|
    @matchings[backup_model][item.id] = yield(item)
  end
end

#build_index(backup_model, keys) ⇒ Object


112
113
114
115
116
117
118
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 112

def build_index(backup_model, keys)
  @indexes[backup_model] = []
  self[backup_model].each do |item|
    unique_code = keys.collect { |k| item.send(k) }.join('-')
    @indexes[backup_model] << unique_code
  end
end

#import(backup_model, *args) ⇒ Object


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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 146

def import(backup_model, *args)
  # puts "Import #{backup_model.to_s.red}"
  # puts self[backup_model].first.inspect.yellow
  options = args.extract_options!
  keys = args
  keys << :name if keys.empty?
  columns = self.class.schema[backup_model.to_s.pluralize.to_sym].delete_if do |c|
    %i[company_id creator_id updater_id id lock_version].include? c
  end
  keys.each do |key|
    raise "Invalid key for record identification: #{key}" unless columns.include? key
  end
  renamings = columns.keys.each_with_object({}) do |k, h|
    h[k] = { comment: :description, department_id: :team_id }[k] || k
    h
  end
  converters = options.delete(:converters) || {}
  default_values = options[:default_values] || {}
  if options[:rename]
    options[:rename].each do |old_column, new_column|
      raise "What is #{old_column}? #{columns.keys.sort.to_sentence} only are accepted." unless columns.keys.include?(old_column)
      renamings[old_column] = new_column
    end
  end
  model = options[:model] || backup_model
  klass = model.to_s.camelcase.constantize

  # Look for doubles
  uniqify_doubles!(backup_model, keys, options.slice(:undoubler, :undoubler_separator))

  browse_and_match(backup_model) do |item|
    # puts item.inspect.magenta
    finder = keys.each_with_object({}) do |key, hash|
      new_column = renamings[key]
      hash.store(new_column, value_of(item, key, columns[key][:references], converters[new_column]))
      hash
    end
    record = klass.find_by(finder) || klass.new
    attributes = {}
    renamings.each do |old_column, new_column|
      unless new_column.nil?
        attributes[new_column] = value_of(item, old_column, columns[old_column][:references], converters[new_column])
      end
    end
    default_values.each do |new_column, value|
      attributes[new_column] ||= value
    end
    record.attributes = attributes
    unless record.valid?
      Rails.logger.warn attributes.inspect
      Rails.logger.warn record.errors.inspect
    end
    record.save!
    record.id
  end
end

#uniqify_doubles!(backup_model, keys, options = {}) ⇒ Object


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
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 120

def uniqify_doubles!(backup_model, keys, options = {})
  build_index(backup_model, keys)
  doubles = @indexes[backup_model].size - @indexes[backup_model].uniq.size
  undoubler = options[:undoubler] || keys.reject { |k| k.to_s =~ /(^|\_)id$/ }.last
  unless doubles.zero?
    dones = []
    separator = options[:undoubler_separator] || '-'
    self[backup_model].each do |item|
      unique_code = keys.collect { |k| item.send(k) }.join('-')
      if dones.include?(unique_code)
        prefix = item.send(undoubler)
        undoubler_value = prefix
        counter = 1
        loop do
          undoubler_value = prefix + separator + counter.to_s
          unique_code = keys.collect { |k| k == undoubler ? undoubler_value : item.send(k) }.join('-')
          break unless dones.include?(unique_code)
          counter += 1
        end
        item.send("#{undoubler}=", undoubler_value)
      end
      dones << unique_code
    end
  end
end

#value_of(item, old_column, references = nil, converter = nil) ⇒ Object


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
# File 'app/exchangers/ekylibre/backup_exchanger.rb', line 82

def value_of(item, old_column, references = nil, converter = nil)
  value = nil
  if converter
    value = converter.call(item)
  else
    value = item[old_column]
    if references
      if references =~ /^\~/ && (ref = item[references[1..-1]])
        ref = ref.underscore
        if ref.blank?
          value = nil
        elsif @matchings[ref]
          value = @matchings[ref][value]
        else
          Rails.logger.warn "Cannot match #{ref.inspect} ##{value.inspect} (polymorphic)"
          value = nil
        end
      else
        if @matchings[references]
          value = @matchings[references][value]
        else
          Rails.logger.warn "Cannot find #{references.inspect} ##{value.inspect}"
          value = nil
        end
      end
    end
  end
  value
end