Class: DocumentTemplate

Inherits:
Ekylibre::Record::Base show all
Defined in:
app/models/document_template.rb

Overview

Sources are stored in :private/reporting/:id/content.xml

Constant Summary collapse

@@load_path =
[]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Ekylibre::Record::Base

#already_updated?, attr_readonly_with_conditions, #check_if_destroyable?, #check_if_updateable?, columns_definition, complex_scopes, customizable?, #customizable?, #customized?, #destroyable?, #editable?, has_picture, #human_attribute_name, human_attribute_name_with_id, nomenclature_reflections, #old_record, #others, refers_to, scope_with_registration, simple_scopes, #updateable?

Instance Attribute Details

#sourceObject

Returns source value


138
139
140
# File 'app/models/document_template.rb', line 138

def source
  @source
end

Class Method Details

.load_defaults(options = {}) ⇒ Object

Loads in DB all default document templates


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 'app/models/document_template.rb', line 262

def load_defaults(options = {})
  locale = (options[:locale] || Preference[:language] || I18n.locale).to_s
  Ekylibre::Record::Base.transaction do
    manageds = where(managed: true).select(&:destroyable?)
    for nature in self.nature.values
      if source = template_fallbacks(nature, locale).detect(&:exist?)
        File.open(source, 'rb:UTF-8') do |f|
          unless template = find_by(nature: nature, managed: true)
            template = new(nature: nature, managed: true, active: true, by_default: false, archiving: 'last')
          end
          manageds.delete(template)
          template.attributes = { source: f, language: locale }
          template.name ||= template.nature.l
          template.save!
        end
        Rails.logger.info "Load a default document template #{nature}"
      else
        Rails.logger.warn "Cannot load a default document template #{nature}: No file found at #{source}"
      end
    end
    destroy(manageds.map(&:id))
  end
  true
end

Print document with default active template for the given nature Returns nil if no template found.


226
227
228
229
230
231
# File 'app/models/document_template.rb', line 226

def print(nature, datasource, key, format = :pdf, options = {})
  if template = find_by(nature: nature, by_default: true, active: true)
    return template.print(datasource, key, format, options)
  end
  nil
end

.sources_rootObject

Returns the root directory for the document templates's sources


234
235
236
# File 'app/models/document_template.rb', line 234

def sources_root
  Ekylibre::Tenant.private_directory.join('reporting')
end

.template_fallbacks(nature, locale) ⇒ Object

Compute fallback chain for a given document nature


239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'app/models/document_template.rb', line 239

def template_fallbacks(nature, locale)
  stack = []
  load_path.each do |path|
    root = path.join(locale, 'reporting')
    stack << root.join("#{nature}.xml")
    stack << root.join("#{nature}.jrxml")
    fallback = {
      sales_order: :sale,
      sales_estimate: :sale,
      sales_invoice: :sale,
      purchases_order: :purchase,
      purchases_estimate: :purchase,
      purchases_invoice: :purchase
    }[nature.to_sym]
    if fallback
      stack << root.join("#{fallback}.xml")
      stack << root.join("#{fallback}.jrxml")
    end
  end
  stack
end

Instance Method Details

#document(data_or_path, key, _format, options = {}) ⇒ Object

Archive the document using the given archiving method


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/models/document_template.rb', line 191

def document(data_or_path, key, _format, options = {})
  return nil if archiving_none? || archiving_none_of_template?

  # Gets historic of document
  archives = Document.where(nature: nature, key: key).where.not(template_id: nil)
  archives_of_template = archives.where(template_id: id)

  # Checks if archiving is expected
  return nil unless (archiving_first? && archives.empty?) ||
                    (archiving_first_of_template? && archives_of_template.empty?) ||
                    archiving.to_s =~ /\A(last|all)(\_of\_template)?\z/

  # Lists last documents to remove after archiving
  removables = []
  if archiving_last?
    removables = archives.pluck(:id)
  elsif archiving_last_of_template?
    removables = archives_of_template.pluck(:id)
  end

  # Creates document if not exist
  document = Document.create!(nature: nature, key: key, name: (options[:name] || tc('document_name', nature: nature.l, key: key)), file: File.open(data_or_path), template_id: id)

  # Removes useless docs
  Document.destroy removables

  document
end

#export(datasource, key, format = :pdf, options = {}) ⇒ Object

Export a document with the given datasource and return path file Store if needed by template

Parameters:

  • datasource

    XML representation of data used by the template


167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'app/models/document_template.rb', line 167

def export(datasource, key, format = :pdf, options = {})
  # Load the report
  report = Beardley::Report.new(source_path, locale: 'i18n.iso2'.t)
  # Call it with datasource
  path = Pathname.new(report.to_file(format, datasource))
  # Archive the document according to archiving method. See #document method.
  if document = self.document(path, key, format, options)
    FileUtils.rm_rf(path)
    path = document.file.path(:original)
  end
  # Returns only the path
  path
end

#formatsObject

Returns the list of formats of the templates


182
183
184
# File 'app/models/document_template.rb', line 182

def formats
  (self['formats'].blank? ? Ekylibre::Reporting.formats : self['formats'].strip.split(/[\s\,]+/))
end

#formats=(value) ⇒ Object


186
187
188
# File 'app/models/document_template.rb', line 186

def formats=(value)
  self['formats'] = (value.is_a?(Array) ? value.join(', ') : value.to_s)
end

Print a document with the given datasource and return raw data Store if needed by template

Parameters:

  • datasource

    XML representation of data used by the template


153
154
155
156
157
158
159
160
161
162
# File 'app/models/document_template.rb', line 153

def print(datasource, key, format = :pdf, options = {})
  # Load the report
  report = Beardley::Report.new(source_path, locale: 'i18n.iso2'.t)
  # Call it with datasource
  data = report.send("to_#{format}", datasource)
  # Archive the document according to archiving method. See #document method.
  document(data, key, format, options)
  # Returns only the data (without filename)
  data
end

#source_dirObject

Returns the expected dir for the source file


141
142
143
# File 'app/models/document_template.rb', line 141

def source_dir
  self.class.sources_root.join(id.to_s)
end

#source_pathObject

Returns the expected path for the source file


146
147
148
# File 'app/models/document_template.rb', line 146

def source_path
  source_dir.join('content.xml')
end