class Treasurer
Some thoughts on double entry accounting:
assets - liabilities = equity where equity = equity_at_start + income - expenses
so
assets - liabilities = equity_at_start + income - expenses
or alternatively
assets + expenses = equity_at_start + income + liabilities (1)
Good things:
Positive equity_at_start, positive assets, positive income, negative liabilities, negative expenses
A debit on the left of (1) must be matched by a credit on the right of (1) and vice versa.
A debit to an asset account increases the value of the asset. This means buying some land or supplies or depositing some cash in a bank account. You can think of it as a debit because you are locking up your equity in a way that may not be realisable. A credit to the asset account means drawing down on the asset, for example selling a bit of land or taking money out of a bank account.
Similarly, a debit to an expense account, effectively, spending money on that expense, increases the value of that account. Debits here are clearly negative things from the point of view of your wealth! (Credits to expense accounts would be something like travel reimbursements).
A credit to income increases the value of the income account… this seems obvious. If you credit income you must debit assets (you have to put your income somewhere, for example a bank account, i.e. you must effectively spend it by buying an asset: remember a bank may fail… a bank account is an asset with risk just as much as a painting).
A credit to liabilities increases the value of the liability, for example taking out a loan. Once you credit a liability you have to either buy (debit) an asset, or buy (debit) an expense directly (for example a loan to pay some fees).
In any accounting period, the sum of all debits and credits should be 0. Also, at the end of the accounting period,
equity_at_end = assets - liabilities = equity_at_start + income - expenses
This seems obvious to me!!
Constants
- SCRIPT_FOLDER
Public Class Methods
# File lib/treasurer/commands.rb, line 4 def add_file(file, account, copts={}) load_treasurer_folder(copts) ep 'entries', Dir.entries CodeRunner.submit(p: "{data_file: '#{File.expand_path(file)}', account: :#{account}}") end
# File lib/treasurer/commands.rb, line 9 def add_folder_of_files(folder, copts={}) #Dir.chdir(folder) do files = Dir.entries(folder).grep(/\.csv$/) accounts = files.map{|f| f.sub(/\.csv/, '')} files = files.map{|f| folder + '/' + f} p ['files789', files, accounts] files.zip(accounts).each{|f,a| add_file(f, a, copts)} #end end
# File lib/treasurer/commands.rb, line 32 def assign(copts={}) load_treasurer_folder(copts) crcopts = eval(copts[:C]||"{}") #crcopts[:h] = nil #CodeRunner.run_command('generate_component_runs', crcopts) crcopts[:h] = :component crcopts[:O] = 'date' crcopts[:f] = 'not (component_runs and component_runs.size > 0 and component_runs[0].instance_variable_get(:@external_account))' crcopts[:f] = 'not (@external_account and @sub_account)' catch (:quit_data_entry) do CodeRunner.run_command('external_account', crcopts) end end
# File lib/treasurer/commands.rb, line 18 def check_is_treasurer_folder raise "This folder has not been set up to use with Treasurer; please initialise a folder with treasurer init" unless FileTest.exist? '.code_runner_script_defaults.rb' and eval(File.read('.code_runner_script_defaults.rb'))[:code] == 'budget' end
# File lib/treasurer/commands.rb, line 21 def create_report(copts = {}) reporter = fetch_reporter(copts) reporter.report() end
# File lib/treasurer/commands.rb, line 25 def fetch_reporter(copts = {}) load_treasurer_folder(copts) Reporter.new( CodeRunner.fetch_runner(h: :component), days_before: copts[:b]||360, days_ahead: copts[:a]||180, today: copts[:t], report_currency: copts[:r]) end
# File lib/treasurer/commands.rb, line 49 def init_root_folder(folder, copts={}) raise "Folder already exists" if FileTest.exist? folder FileUtils.makedirs(folder) FileUtils.cp( SCRIPT_FOLDER + '/treasurer/local_customisations.rb', folder + '/local_customisations.rb') CodeRunner.fetch_runner(Y: folder, C: 'budget', X: '/dev/null') init_sqlite(folder) eputs "\n\n Your treasurer folder '#{folder}' has been set up. All further treasurer commands should be run from within this folder.\n" end
# File lib/treasurer/commands.rb, line 59 def init_sqlite(folder) CodeRunner::Budget.init_sqlite(folder) end
# File lib/treasurer/commands.rb, line 73 def list_last_updated(copts={}) reporter = fetch_reporter(copts) reporter.generate_accounts accts = reporter.accounts.find_all{|ac| not ac.external and not ac.type==:Equity} puts "Account | Date " accts.each do |ac| #puts ac.name puts "#{ac.name} | #{ac.runs.sort_by{|r| r.date}[-1].date.to_s}" end end
# File lib/treasurer/commands.rb, line 62 def load_treasurer_folder(copts={}) check_is_treasurer_folder Treasurer.send(:remove_const, :LocalCustomisations) if defined? Treasurer::LocalCustomisations load 'local_customisations.rb' Treasurer::Reporter.send(:include, Treasurer::LocalCustomisations) Treasurer::Reporter::Account.send(:include, Treasurer::LocalCustomisations) Treasurer::Reporter::Analysis.send(:include, Treasurer::LocalCustomisations) require 'budgetcrmod' CodeRunner::Budget.send(:include, Treasurer::LocalCustomisations) _runner = CodeRunner.fetch_runner(eval(copts[:C]||"{}")) end
# File lib/treasurer/commands.rb, line 84 def method_missing(meth, *args) CodeRunner.send(meth, *args) end
This function gets called before every command and allows arbitrary manipulation of the command options (copts) hash
# File lib/treasurer.rb, line 98 def setup(copts) # None neededed #copts[:b] = copts[:b].to_i if copts[:b] #copts[:a] = copts[:a].to_i if copts[:a] copts[:t] = Date.parse(copts[:t]) if copts[:t] end
# File lib/treasurer/commands.rb, line 45 def status(copts={}) load_treasurer_folder(copts) CodeRunner.status(eval(copts[:C]||"{}")) end
# File lib/treasurer.rb, line 104 def verbosity 2 end