Class: RockBooks::JournalEntryBuilder

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

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#journal_entry_contextObject

Returns the value of attribute journal_entry_context

Returns:

  • (Object)

    the current value of journal_entry_context



9
10
11
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 9

def journal_entry_context
  @journal_entry_context
end

Instance Method Details

#acct_amounts_from_tokens(tokens, date) ⇒ Object

A “token” in this context means an account name and account amount pair, e.g. “pnc.checking 1234.56”.

Parameters:

  • tokens

    the account name/amount pairs found in the source text

Returns:

  • array of AcctAmount instances



21
22
23
24
25
26
27
28
29
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 21

def acct_amounts_from_tokens(tokens, date)
  acct_amounts = []

  tokens[0..-1].each_slice(2).each do |(, amount)|
    acct_amounts <<  AcctAmount.create_with_chart_validation(date, , amount, journal_entry_context)
  end

  acct_amounts
end

#buildObject



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 138

def build
  # this is an account line in the form: yyyy-mm-dd 101 blah blah blah
  tokens = line.split
  acct_amount_tokens = tokens[1..-1]
  date_string = journal.date_prefix + tokens[0]

  raise_date_format_error = -> do
    raise Error.new("Date string was '#{date_string}' but should be a valid date in the form YYYY-MM-DD in " + \
        "journal '#{journal_entry_context[:journal].title}', line #{journal_entry_context[:linenum]}.")
  end

  raise_date_format_error.() if date_string.length != 10

  begin
    date = Date.iso8601(date_string)
  rescue ArgumentError
    raise_date_format_error.()
  end

  unless chart_of_accounts.included_in_period?(date)
    raise DateRangeError.new(date, chart_of_accounts.start_date,
        chart_of_accounts.end_date, journal_entry_context)
  end

  acct_amounts = build_acct_amount_array(date, acct_amount_tokens)
  validate_transaction_is_balanced(acct_amounts)
  JournalEntry.new(date, acct_amounts, journal.short_name)
end

#build_acct_amount_array(date, tokens) ⇒ Object

Returns an array of AcctAmount instances for the array of tokens.

The following applies only to regular (not general) journals:

this token array will start with the transaction’s total amount and be followed by account/amount pairs.

Examples, assuming a line: 2018-05-20 5.79 701 1.23 702 4.56

and the journal account is ‘101’, ‘D’ ‘My Checking Account’, the following AcctAmoutns will be created:

AcctAmount code: ‘101’, amount: -5.79, AcctAmount code: ‘701’, 1.23, AcctAmount code: ‘702’, 4.56,

shortcut: if there is only 1 account (that is, it is not a split entry), give it the total amount

‘5.79’, ‘701’

–> [AcctAmount code: ‘101’, amount: -5.79, AcctAmount code: ‘701’, 5.79]

If the account is a credit account, the signs will be reversed.



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_entry_builder.rb', line 91

def build_acct_amount_array(date, tokens)

  unless general_journal?
    if journal..nil?
      raise Error.new("An '@account_code: ' line has not yet been specified in this journal." )
    end

    # Prepend the array with the document account code so that total amount will be associated with it.
    tokens.unshift(journal.)

    # For convenience in regular journals, when there is no split,
    # we permit the user to omit the amount after the
    # account code, since we know it will be equal to the total amount.
    # We add it here, because we *will* need to include it in the data.
    if tokens.size == 3
      tokens << tokens[1]  # copy the total amount to the sole account's amount
    end
  end

  validate_acct_amount_token_array_size(tokens)

  # Tokens in the odd numbered positions are dollar amounts that need to be converted from string to float.
  begin
    convert_amounts_to_floats(tokens)
  rescue ArgumentError
    raise Error.new("Float conversion or other parse error for #{date}, #{tokens}.")
  end

  unless general_journal?
    # As a convenience, all normal journal amounts are entered as positive numbers.
    # This code negates the amounts as necessary so that debits are + and credits are -.
    # In general journals, the debit and credit amounts must be entered correctly already.
    convert_signs_for_debit_credit(tokens)
  end

  acct_amounts_from_tokens(tokens, date)
end

#chart_of_accountsObject



14
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 14

def chart_of_accounts; journal_entry_context.chart_of_accounts;  end

#convert_amounts_to_floats(tokens) ⇒ Object



39
40
41
42
43
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 39

def convert_amounts_to_floats(tokens)
  (1...tokens.size).step(2) do |amount_index|
    tokens[amount_index] = Float(tokens[amount_index])
  end
end

#convert_signs_for_debit_credit(tokens) ⇒ Object

For regular journal only, not general journal. This converts the entered signs to the correct debit/credit signs.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 53

def convert_signs_for_debit_credit(tokens)

  # Adjust the sign of the amount for the main journal account (e.g. the checking account or credit card account)
  # e.g. If it's a checking account, it is an asset, a debit account, and the transaction total
  # will represent a credit to that checking account.
   = ->(amount) do
    (journal.debit_or_credit == :debit) ? -amount : amount
  end

  adjust_sign_for_other_accounts = ->(amount) do
    - .(amount)
  end

  tokens[1] = .(tokens[1])
  (3...tokens.size).step(2) do |amount_index|
    tokens[amount_index] = adjust_sign_for_other_accounts.(tokens[amount_index])
  end
end

#general_journal?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 46

def general_journal?
  journal.doc_type == 'general_journal'
end

#journalObject



11
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 11

def journal;           journal_entry_context.journal;            end

#lineObject



13
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 13

def line;              journal_entry_context.line;               end

#linenumObject



12
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 12

def linenum;           journal_entry_context.linenum;            end

#validate_acct_amount_token_array_size(tokens) ⇒ Object



32
33
34
35
36
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 32

def validate_acct_amount_token_array_size(tokens)
  if tokens.size.odd?
    raise IncorrectSequenceError.new(tokens, journal_entry_context)
  end
end

#validate_transaction_is_balanced(acct_amounts) ⇒ Object



130
131
132
133
134
135
# File 'lib/rock_books/documents/journal_entry_builder.rb', line 130

def validate_transaction_is_balanced(acct_amounts)
  sum = acct_amounts.map(&:amount).sum.round(4)
  unless sum == 0.0
    raise TransactionNotBalancedError.new(sum, journal_entry_context)
  end
end