Skip to content

Instantly share code, notes, and snippets.

@jokester
Created March 1, 2020 10:56
Show Gist options
  • Save jokester/be548dd3fefd478adcd406519a648c88 to your computer and use it in GitHub Desktop.
Save jokester/be548dd3fefd478adcd406519a648c88 to your computer and use it in GitHub Desktop.
my beancount importers
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
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
#!/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