Created
March 1, 2020 10:56
-
-
Save jokester/be548dd3fefd478adcd406519a648c88 to your computer and use it in GitHub Desktop.
my beancount importers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Converter | |
class BaseConverter | |
def initialize input_file, **options | |
@input_file = input_file | |
@options = options | |
end | |
def write output_file, force: false | |
if output_file.exist? && !force | |
puts " NOT overwriting #{output_file}. remove dest file and rerun or specify 'force' flag" | |
else | |
Pathname.new(output_file).write convert | |
puts " written to #{output_file}." | |
end | |
end | |
private def read | |
# see https://qiita.com/kentakozuka/items/d874a572ddf6cc34213f | |
NKF.nkf '-w -g', Pathname.new(@input_file).binread | |
end | |
protected def convert | |
throw 'override me' | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require_relative 'converter_base' | |
module Converter | |
class WechatPay < BaseConverter | |
def convert | |
raw_rows.map {|row| | |
p case row['交易类型'] | |
when /^微信红包/ | |
convert_red_packet row | |
when '商户消费', /-退款$/, /扫二维码付款/ | |
convert_transaction_row row | |
when '转账' | |
convert_transfer_row row | |
else | |
throw row | |
end | |
}.flatten.join("\n") | |
end | |
def convert_red_packet hash | |
date = hash['交易时间'].split[0] | |
rmb_amount = hash['金额(元)'][1..-1] # to strip '¥' | |
another_account_symbol = if hash['收/支'] == '收入' then '-' else '+' end | |
if hash['交易类型'] === '微信红包' && hash['收/支'] === '收入' | |
another_account = 'Income:Other' | |
elsif hash['交易类型'] === '微信红包-退款' && hash['收/支'] === '收入' | |
another_account = 'Expenses:Other' | |
elsif hash['收/支'] === '支出' | |
another_account = 'Expenses:Other' | |
else | |
throw "cannot figure out redpacket action: #{hash}" | |
end | |
[ | |
"#{date} * #{'微信红包'.to_json} #{hash['交易对方'].to_json}", | |
" #{another_account} #{another_account_symbol}#{rmb_amount}RMB ", | |
" #{@options[:account]}", | |
'', | |
] | |
end | |
def convert_transaction_row hash | |
date = hash['交易时间'].split[0] | |
recipient = hash['交易对方'] | |
remark = hash['商品'] | |
another_account = 'Expenses:TODO' | |
rmb_amount = hash['金额(元)'][1..-1] # to strip '¥' | |
another_account_symbol = if hash['收/支'] == '收入' then '-' else '+' end | |
[ | |
"#{date.tr('/', '-')} * #{recipient.to_json} #{remark.to_json}", | |
" #{another_account} #{another_account_symbol}#{rmb_amount}RMB", | |
" #{@options[:account]}", | |
'', | |
] | |
end | |
def convert_transfer_row hash | |
date = hash['交易时间'].split[0] | |
recipient = hash['交易对方'] | |
remark = hash['商品'] | |
rmb_amount = hash['金额(元)'][1..-1] # to strip '¥' | |
if hash['收/支'] == '收入' | |
another_account_symbol = '-' | |
another_account = 'Income:TODO' | |
else | |
another_account_symbol = '+' | |
another_account = 'Expenses:TODO' | |
end | |
[ | |
"#{date.tr('/', '-')} * #{recipient.to_json} #{remark.to_json}", | |
" #{another_account} #{another_account_symbol}#{rmb_amount}RMB", | |
" #{@options[:account]}", | |
'', | |
] | |
end | |
def raw_rows | |
rows = (CSV.parse read) | |
if rows[15][0] == '----------------------微信支付账单明细列表--------------------' | |
rows[17..-1].reverse.map{|r| Hash[ rows[16].zip r ]} | |
else | |
throw "cannot recognize start of bills. got #{rows[15][0]}" | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'pathname' | |
require 'nkf' | |
require 'csv' | |
require 'json' | |
require_relative 'converter_wechatpay' | |
REPO_ROOT = Pathname.new(__FILE__).join('..', '..') | |
RAW_ROOT = REPO_ROOT.join('book', 'raw') | |
GENERATED_ROOT = REPO_ROOT.join('book', 'generated') | |
def main | |
RAW_ROOT.children.sort_by(& | |
to_s).each do |input_file| | |
output_file = GENERATED_ROOT.join "#{input_file.basename}.beancount" | |
puts "converting #{input_file} to #{output_file}" | |
case input_file.basename.to_s | |
when /wechat-1-.*\.csv$/i | |
Converter::WechatPay.new(input_file, account: 'Assets:Wechat:Main') | |
.write(output_file) | |
else | |
puts "unmatched file: #{input_file}" | |
fail "no idea what to do" | |
end | |
end | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment