Blogaomu

WEBアプリケーション開発とその周辺のメモをゆるふわに書いていきます。

Rubyで確定申告楽したい2019

今年も無事に確定申告が終わりました。昨年3月のkzrbで確定申告用のスクリプトを作った話をしたのですが、その続き。

www.blogaomu.com

去年の時点では以下の機能が実装されていました。

  • 金融機関からダウンロード済みのCSVファイルを読み込む
  • 金融機関毎にCSVデータをパースしてオブジェクトの配列にする

特定の支払いを抽出するのはできていたのですが、経費としてfreeeに登録するのは手動で行っていたのでfreeeにインポートできる形式でファイル出力する機能を実装しました。今回実装したのは以下になります。

  • 金融機関毎のデータオブジェクトをfreeeインポート用データオブジェクトに変換する
  • freeeデータオブジェクトの配列をCSVファイルに出力する
  • 一連の処理を rake タスク化

freeeの取引インポート機能についてはこちらを参照。 support.freee.co.jp

処理の詳細

こんな感じでデータを表すクラスと処理(=今回はCSV出力)を扱うクラスを作成。属性の名前はfreeeさんのhtmlから拝借しました🙇 Freee#export の datas には FreeeData の配列が渡ってくる想定。

require 'csv'

class FreeeData
  attr_reader :deal_type # 収支区分
  attr_reader :admin_number # 管理番号
  attr_reader :date # 発生日
  attr_reader :settlement_date # 決済期日
  attr_reader :partner # 取引先
  attr_reader :account_item # 勘定科目
  attr_reader :tax # 税区分
  attr_reader :amount # 金額
  attr_reader :tax_calculate_type # 税計算区分
  attr_reader :tax_amount # 税額
  attr_reader :description # 備考
  attr_reader :item # 品目
  attr_reader :section # 部門
  attr_reader :default # メモタグ
  attr_reader :transaction_date # 決済日
  attr_reader :walletable_name # 決済口座
  attr_reader :settlement_amount # 決済金額

  def initialize(**params)
    params
      .select {|k,v| self.methods.include?(k) }
      .each {|k,v| self.instance_variable_set("@#{k}".to_sym, v)}
  end
end

class Freee
  def export(datas, filename)
    option = {
      encoding: 'Shift_JIS'
    }
    CSV.open(filename, 'wb', option) do |csv|
      csv << ['収支区分','管理番号','発生日','決済期日','取引先','勘定科目','税区分','金額','税計算区分','税額','備考','品目','部門','メモタグ(複数指定可、カンマ区切り)','決済日','決済口座','決済金額']
      datas.each do |d|
        csv << [d.deal_type, d.admin_number, d.date, d.settlement_date, d.partner, d.account_item, d.tax, d.amount, d.tax_calculate_type, d.tax_amount, d.description, d.item, d.section, d.default, d.transaction_date, d.walletable_name, d.settlement_amount]
      end
    end
  end
end

初期化処理はこちらを参考にしました。ありがとうございます。

tex2e.github.io

そして、もともと実装済みの金融機関毎の処理に FreeeData オブジェクトへ変換する処理を実装。なんかデータ変換ロジックって誰が知っていると都合が良いのか分からず、いったん金融機関データクラスに実装してしまった。ここで時間を使うよりも確定申告処理に時間を使いたかったので雑になったのは言い訳です。

# 実装イメージ(なんかしっくりこない)
# 金融機関のデータを表すクラス
class HogeBankData
  attr_reader :date
  # ...

  def convert_to_free
    # 銀行データは FreeeData について知っている必要がある???
    FreeData.new(
      date: date.strftime('%Y/%m/%d'),
      # ...
    )
  end
end

# 処理クラス
class HogeBank
  def import(filename)
    # ...
  end
end

ともかく、金融機関のデータリストからfreeeインポート用のデータに変換してファイルに出力するという処理の流れを作る準備ができました。今までどおりreplでポチポチやってもいいのですが、さすがにだるいので rake タスクにしてコマンド一発でファイル出力できるようにしておきました。

# これも実装イメージ
$LOAD_PATH.push('lib')

require 'hoge_bank'
require 'fuga_card'
require 'freee'

task :export do
  hoge = HogeBank.new
  hoge.import('data/hoge_bank/data.csv')
  f_data = hoge.parsed_data.select {|d| d.is_transaction_for_freee? }.map {|d| d.convert_to_freee }
  fuga = FugaCard.new
  Dir.glob('data/fuga_card/*.csv') do |csv| # 月別にCSVファイルがあるパターン
    fuga.import(csv)
  end
  f_data += fuga.parsed_data.select {|d| d.is_transaction_for_freee? }.map {|d| d.convert_to_freee }
  
  freee = Freee.new
  freee.export(f_data, 'freee.csv')
end

感想

  • 目視確認して手入力していた去年に比べて自動化が進み楽になった
  • とはいいつつ申告期限もあったので、雑に作った節は否めない
  • マッピングのところは泥臭くなってしまう
  • 何年か振りに Rakefile 触った
  • 来年は金融機関のサイトからCSVファイルをダウンロードするところを自動化したい(スクレイピング行けるんだろうか)