Class: RVGP::Reconcilers::CsvReconciler

Inherits:
Base::Reconciler show all
Extended by:
Utilities
Defined in:
lib/rvgp/reconcilers/csv_reconciler.rb

Overview

This reconciler is instantiated for input files of type csv. Additional parameters are supported in the :format section of this reconciler, which are documented in RVGP::Reconcilers under the ‘CSV specific format parameters’ section.

Instance Attribute Summary collapse

Attributes inherited from Base::Reconciler

#balances, #cash_back, #cash_back_to, #default_currency, #disable_checks, #expense_rules, #file, #from, #income_rules, #input_file, #label, #output_file, #reverse_order, #starts_on, #tag_accounts

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utilities

months_through, string_to_regex

Methods inherited from Base::Reconciler

all, #as_taskname, #dependencies, #to_ledger, #to_ledger!

Constructor Details

#initialize(yaml) ⇒ CsvReconciler

Returns a new instance of CsvReconciler.

Raises:



329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 329

def initialize(yaml)
  super yaml

  missing_fields = if yaml.key? :format
                     if yaml[:format].key?(:fields)
                       %i[date amount description].map do |attr|
                         format('format/fields/%s', attr) unless yaml[:format][:fields].key?(attr)
                       end.compact
                     else
                       ['format/fields']
                     end
                   else
                     ['format']
                   end

  raise MissingFields.new(*missing_fields) unless missing_fields.empty?

  @fields_format = yaml[:format][:fields] if yaml[:format].key? :fields
  @encoding_format = yaml[:format][:encoding] if yaml[:format].key? :encoding
  @invert_amount = yaml[:format][:invert_amount] || false if yaml[:format].key? :invert_amount
  @skip_lines = yaml[:format][:skip_lines]
  @trim_lines = yaml[:format][:trim_lines]
  @csv_format = { headers: yaml[:format][:csv_headers] } if yaml[:format].key? :csv_headers
end

Instance Attribute Details

#csv_formatHash (readonly)

This hash is sent to the options parameter of CSV.parse

Returns:

  • (Hash)

    the current value of csv_format



326
327
328
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 326

def csv_format
  @csv_format
end

#fields_formatHash<String, <Proc,String,Integer>> (readonly)

A hash of field names, to their location in the input file. Supported key names include: date, amount, description. These keys can map to either a ‘string’ type (indicating which column of the input file contains the key’s value). An Integer (indicating which column offset contains the key’s value). Or, a Proc (which executes for every row in the input file, and whose return value will be used)

Returns:

  • (Hash<String, <Proc,String,Integer>>)

    the current value of fields_format



326
327
328
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 326

def fields_format
  @fields_format
end

#invert_amountBoolean (readonly)

Whether or not to multiple the :amount field by negative one.

Returns:

  • (Boolean)

    the current value of invert_amount



326
327
328
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 326

def invert_amount
  @invert_amount
end

#skip_lines<Regexp, Integer> (readonly)

Given a regex, the input file will discard the match for the provided regex from the start of the input file. Given an integer, the provided number of lines will be removed from the start of the input file.

Returns:

  • (<Regexp, Integer>)

    the current value of skip_lines



326
327
328
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 326

def skip_lines
  @skip_lines
end

#trim_lines<Regexp, Integer> (readonly)

Given a regex, the input file will discard the match for the provided regex from the end of the input file. Given an integer, the provided number of lines will be removed from the end of the input file.

Returns:

  • (<Regexp, Integer>)

    the current value of trim_lines



326
327
328
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 326

def trim_lines
  @trim_lines
end

Class Method Details

.input_file_contents(contents, skip_lines = nil, trim_lines = nil) ⇒ Object

Mostly this is a class mathed, to make testing easier



358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
# File 'lib/rvgp/reconcilers/csv_reconciler.rb', line 358

def input_file_contents(contents, skip_lines = nil, trim_lines = nil)
  start_offset = 0
  end_offset = contents.length

  if trim_lines
    trim_lines_regex = string_to_regex trim_lines.to_s
    trim_lines_regex ||= /(?:[^\n]*\n?){0,#{trim_lines}}\Z/m
    match = trim_lines_regex.match contents
    end_offset = match.begin 0 if match
    return String.new if end_offset.zero?
  end

  if skip_lines
    skip_lines_regex = string_to_regex skip_lines.to_s
    skip_lines_regex ||= /(?:[^\n]*\n){0,#{skip_lines}}/m
    match = skip_lines_regex.match contents
    start_offset = match.end 0 if match
  end

  # If our cursors overlapped, that means we're just returning an empty string
  return String.new if end_offset < start_offset

  contents[start_offset..(end_offset - 1)]
end