Class: RockBooks::Journal

Inherits:
Object
  • Object
show all
Defined in:
lib/rock_books/documents/journal.rb

Overview

The journal will create journal entries, each of which containing an array of account/amount objects, copying the entry date to them.

Warning: Any line beginning with a number will be assumed to be the date of a data line for an entry, so descriptions cannot begin with a number.

Defined Under Namespace

Classes: Entry

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chart_of_accounts, input_lines) ⇒ Journal

short_name is a name that will appear on reports identifying the journal from which a transaction comes



68
69
70
71
72
73
74
75
76
# File 'lib/rock_books/documents/journal.rb', line 68

def initialize(chart_of_accounts, input_lines)
  @chart_of_accounts = chart_of_accounts
  @entries = []
  @date_prefix = ''
  input_lines.each_with_index do |line, linenum|
    context = JournalEntryContext.new(self, linenum + 1, line)
    parse_line(context)
  end
end

Instance Attribute Details

#account_codeObject (readonly)

Returns the value of attribute account_code.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def 
  @account_code
end

#chart_of_accountsObject (readonly)

Returns the value of attribute chart_of_accounts.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def chart_of_accounts
  @chart_of_accounts
end

#date_prefixObject (readonly)

Returns the value of attribute date_prefix.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def date_prefix
  @date_prefix
end

#debit_or_creditObject (readonly)

Returns the value of attribute debit_or_credit.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def debit_or_credit
  @debit_or_credit
end

#doc_typeObject (readonly)

Returns the value of attribute doc_type.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def doc_type
  @doc_type
end

#entriesObject (readonly)

Returns the value of attribute entries.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def entries
  @entries
end

#short_nameObject (readonly)

Returns the value of attribute short_name.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def short_name
  @short_name
end

#titleObject (readonly)

Returns the value of attribute title.



65
66
67
# File 'lib/rock_books/documents/journal.rb', line 65

def title
  @title
end

Class Method Details

.acct_amounts_in_documents(documents, entries_filter = nil, acct_amounts_filter = nil) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/rock_books/documents/journal.rb', line 48

def self.acct_amounts_in_documents(documents, entries_filter = nil, acct_amounts_filter = nil)
  entries = entries_in_documents(documents, entries_filter)

  acct_amounts = entries.each_with_object([]) do |entry, acct_amounts|
    acct_amounts << entry.acct_amounts
  end.flatten

  if acct_amounts_filter
    acct_amounts = AcctAmount.filter(acct_amounts, filter)
  end

  acct_amounts
end

.entries_in_documents(documents, filter = nil) ⇒ Object

Returns the entries in the specified documents, sorted by date and document short name, optionally filtered with the specified filter.



33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rock_books/documents/journal.rb', line 33

def self.entries_in_documents(documents, filter = nil)
  entries = documents.each_with_object([]) do |document, entries|
    entries << document.entries
  end.flatten

  if filter
    entries = entries.select {|entry| filter.(entry) }
  end

  entries.sort_by do |entry|
    [entry.date, entry.doc_short_name]
  end
end

.from_file(chart_of_accounts, file) ⇒ Object



21
22
23
# File 'lib/rock_books/documents/journal.rb', line 21

def self.from_file(chart_of_accounts, file)
  self.new(chart_of_accounts, File.readlines(file).map(&:chomp))
end

.from_string(chart_of_accounts, string) ⇒ Object



26
27
28
# File 'lib/rock_books/documents/journal.rb', line 26

def self.from_string(chart_of_accounts, string)
  self.new(chart_of_accounts, string.split("\n"))
end

Instance Method Details

#==(other) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
# File 'lib/rock_books/documents/journal.rb', line 171

def ==(other)
  # excluding date_prefix from this test intentionally because it does not
  # affect the parsed data.
  short_name        == other.short_name          && \
        == other.        && \
  chart_of_accounts == other.chart_of_accounts   && \
  debit_or_credit   == other.debit_or_credit     && \
  doc_type          == other.doc_type            && \
  title             == other.title               && \
  entries           == other.entries
end

#acct_amountsObject



130
131
132
# File 'lib/rock_books/documents/journal.rb', line 130

def acct_amounts
  entries.each_with_object([]) { |entry, acct_amounts|  acct_amounts << entry.acct_amounts }.flatten
end

#parse_line(journal_entry_context) ⇒ Object



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
# File 'lib/rock_books/documents/journal.rb', line 79

def parse_line(journal_entry_context)
  begin
    line = journal_entry_context.line
    case line.strip
    when /^@doc_type:/
      @doc_type = line.split(/^@doc_type:/).last.strip
    when  /^@account_code:/
      @account_code = line.split(/^@account_code:/).last.strip

      unless chart_of_accounts.include?(@account_code)
        raise AccountNotFoundError.new(@account_code, journal_entry_context)
      end

      # if debit or credit has not yet been specified, inherit the setting from the account:
      unless @debit_or_credit
        @debit_or_credit = chart_of_accounts.debit_or_credit_for_code(@account_code)
      end

    when /^@title:/
      @title = line.split(/^@title:/).last.strip
    when /^@short_name:/
      @short_name = line.split(/^@short_name:/).last.strip
    when /^@date_prefix:/
      @date_prefix = line.split(/^@date_prefix:/).last.strip
    when /^@debit_or_credit:/
      data = line.split(/^@debit_or_credit:/).last.strip
      @debit_or_credit = data.to_sym
    when /^$/
      # ignore empty line
    when /^#/
      # ignore comment line
    when /^\d/  # a date/acct/amount line starting with a number
      entries << JournalEntryBuilder.new(journal_entry_context).build
    else # Text line(s) to be attached to the most recently parsed transaction
      unless entries.last
        raise Error.new("Entry for this description cannot be found: #{line}")
      end
      entries.last.description << line << "\n"

      if /^Receipt:/.match(line)
        receipt_spec = line.split(/^Receipt:/).last.strip
        entries.last.receipts << receipt_spec
      end
    end
  rescue => e
    puts "Error occurred parsing:\n#{journal_entry_context}\n\n"
    raise
  end
end

#to_hObject



155
156
157
158
159
160
161
162
163
164
# File 'lib/rock_books/documents/journal.rb', line 155

def to_h
  {
      title:           title,
      account_code:    ,
      debit_or_credit: debit_or_credit,
      doc_type:        doc_type,
      date_prefix:     date_prefix,
      entries:         entries
  }
end

#to_jsonObject



167
# File 'lib/rock_books/documents/journal.rb', line 167

def to_json; to_h.to_json; end

#to_sObject



145
146
147
148
149
150
151
152
# File 'lib/rock_books/documents/journal.rb', line 145

def to_s
  super.to_s + ': ' + \
  {
      account_code: ,
      debit_or_credit: debit_or_credit,
      title: title
  }.to_s
end

#to_yamlObject



168
# File 'lib/rock_books/documents/journal.rb', line 168

def to_yaml; to_h.to_yaml; end

#total_amountObject



140
141
142
# File 'lib/rock_books/documents/journal.rb', line 140

def total_amount
  AcctAmount.total_amount(acct_amounts)
end

#totals_by_accountObject



135
136
137
# File 'lib/rock_books/documents/journal.rb', line 135

def 
  acct_amounts.each_with_object(Hash.new(0)) { |aa, totals| totals[aa.code] += aa.amount }
end