mirror of
https://github.com/gwenhael-le-moine/ledgerrb.git
synced 2024-12-26 09:59:18 +01:00
crystal
This commit is contained in:
parent
c9140a6aa9
commit
d851767a67
1 changed files with 164 additions and 0 deletions
164
lib/ledger.cr
Normal file
164
lib/ledger.cr
Normal file
|
@ -0,0 +1,164 @@
|
|||
# encoding: utf-8
|
||||
|
||||
require "csv"
|
||||
require "http/server"
|
||||
|
||||
# Ruby wrapper module for calling ledger
|
||||
module Ledger
|
||||
@binary = "ledger"
|
||||
@file = ENV[ "LEDGER_FILE" ]
|
||||
|
||||
def run( options, command = "", command_parameters = "" )
|
||||
STDERR.puts "#{@binary} -f #{@file} #{options} #{command} #{command_parameters}"
|
||||
`#{@binary} -f #{@file} #{options} #{command} #{command_parameters}`
|
||||
end
|
||||
|
||||
def version
|
||||
run "--version"
|
||||
end
|
||||
|
||||
def accounts( depth = 9999 )
|
||||
accounts = run( "", "accounts" )
|
||||
.split( "\n" )
|
||||
.map do |a|
|
||||
a.split( ":" )
|
||||
.each_slice( depth )
|
||||
.to_a.first
|
||||
end.uniq
|
||||
|
||||
accounts.map(&:length).max.times do |i|
|
||||
accounts += accounts.map { |acc| acc.first( i ) }
|
||||
end
|
||||
|
||||
accounts
|
||||
.uniq
|
||||
.sort
|
||||
.reject { |a| a.empty? }
|
||||
.sort_by { |a| a.length }
|
||||
end
|
||||
|
||||
def dates_salaries( category = "salaire" )
|
||||
CSV.parse( run( "", "csv", category ) )
|
||||
.map do |row|
|
||||
Date.parse row[ 0 ]
|
||||
end
|
||||
.uniq
|
||||
end
|
||||
|
||||
def register( period = nil, categories = "" )
|
||||
period = period.nil? ? "" : "-p '#{period}'"
|
||||
|
||||
CSV.parse( run( "--no-revalued --exchange '#{CURRENCY}' #{period}", "csv", categories ) )
|
||||
.map do |row|
|
||||
{ date: row[ 0 ],
|
||||
payee: row[ 2 ],
|
||||
account: row[ 3 ],
|
||||
amount: row[ 5 ],
|
||||
currency: row[ 4 ] }
|
||||
end
|
||||
end
|
||||
|
||||
def balance( cleared = false, depth = nil, period = nil, categories = "" )
|
||||
period = period.nil? ? "" : "-p '#{period}'"
|
||||
depth = depth.nil? ? "" : "--depth #{depth}"
|
||||
operation = cleared ? "cleared" : "balance"
|
||||
|
||||
run( "--flat --no-total --exchange '#{CURRENCY}' #{period} #{depth}", operation, categories )
|
||||
.split( "\n" )
|
||||
.map do |line|
|
||||
line_array = line.split( "#{CURRENCY}" )
|
||||
|
||||
{ account: line_array[ 1 ].strip,
|
||||
amount: line_array[ 0 ].tr( SEPARATOR, "." ).to_f }
|
||||
end
|
||||
end
|
||||
|
||||
# def int_treefied_balance( node )
|
||||
# return { name: node[:account], size: node[:amount] } unless node[:account].include( ":" )
|
||||
|
||||
# { name: node[:account].split(":").first,
|
||||
# children: int_treefied_balance( ... ) }
|
||||
# end
|
||||
|
||||
# def treefeid_balance( cleared = false, depth = nil, period = nil, categories = "" )
|
||||
# bal = balance( cleared, depth, period, categories )
|
||||
|
||||
|
||||
# end
|
||||
|
||||
def cleared
|
||||
run( "--flat --no-total --exchange '#{CURRENCY}'", "cleared", "Assets Equity" )
|
||||
.split( "\n" )
|
||||
.map do |row|
|
||||
fields = row.match( /\s*(\S+ €)\s*(\S+ €)\s*(\S+)\s*(\S+)/ )
|
||||
{ account: fields[ 4 ],
|
||||
amount: { cleared: fields[ 2 ],
|
||||
all: fields[ 1 ] } } unless fields.nil?
|
||||
end
|
||||
end
|
||||
|
||||
def budget( period = nil, categories = "" )
|
||||
period = period.nil? ? "" : "-p '#{period}'"
|
||||
|
||||
budgeted = run( "--flat --no-total --budget --exchange '#{CURRENCY}' #{period}", "budget", categories )
|
||||
.lines
|
||||
.map do |line|
|
||||
ary = line.split
|
||||
|
||||
{ currency: ary[1],
|
||||
amount: ary[0].tr( SEPARATOR, "." ).to_f,
|
||||
budget: ary[2].tr( SEPARATOR, "." ).to_f,
|
||||
percentage: ary.last( 2 ).first.gsub( /%/, "" ).tr( SEPARATOR, "." ).to_f,
|
||||
account: ary.last }
|
||||
end
|
||||
|
||||
unbudgeted_amount = run( "--flat --no-total --unbudgeted -Mn --exchange '#{CURRENCY}' #{period}", "register", categories )
|
||||
.lines
|
||||
.map do |line|
|
||||
line.split[4].tr( SEPARATOR, "." ).to_f
|
||||
end
|
||||
.reduce( :+ )
|
||||
|
||||
budget = budgeted.map { |account| account[:budget] }.reduce( :+ )
|
||||
income = run( "--flat --no-total --unbudgeted -Mn --exchange '#{CURRENCY}' #{period}", "register", "Income" )
|
||||
.lines
|
||||
.last
|
||||
.split[4]
|
||||
.tr( SEPARATOR, "." )
|
||||
.to_f * -1
|
||||
disposable_income = income - budget
|
||||
|
||||
budgeted << { currency: CURRENCY,
|
||||
amount: unbudgeted_amount,
|
||||
budget: disposable_income,
|
||||
percentage: (unbudgeted_amount / disposable_income) * 100,
|
||||
account: "(unbudgeted)" }
|
||||
end
|
||||
|
||||
def graph_values( period = nil, categories = [ "Expenses" ] )
|
||||
period = period.nil? ? "" : "-p '#{period}'"
|
||||
|
||||
result = {} of KeyType => ValueType
|
||||
categories.each do |category|
|
||||
result[ category ] = CSV
|
||||
.parse( run( "-MAn --exchange '#{CURRENCY}' #{period}", "csv --no-revalued", category ) )
|
||||
.map do |row|
|
||||
{ date: row[ 0 ],
|
||||
amount: row[ 5 ],
|
||||
currency: row[ 4 ] }
|
||||
end
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
|
||||
p Ledger#version
|
||||
|
||||
server = HTTP::Server.new(8080) do |context|
|
||||
context.response.content_type = "text/plain"
|
||||
context.response.print Ledger#version # "Hello world, got #{context.request.path}!"
|
||||
end
|
||||
|
||||
puts "Listening on http://127.0.0.1:8080"
|
||||
server.listen
|
Loading…
Reference in a new issue