Ruby

Rubyで国民健康保険料を計算する

Okinawa.rb Advent Calendar 2017 1日目です。
https://qiita.com/advent-calendar/2017/okinawarb

沖縄県の各市町村の国民健康保険料の金額をRubyで計算します。

国民健康保険税

日本は国民皆保険制度なので国民全員がいずれかの公的医療保険制度に加入しています。1

市町村国保とは、他の医療保険に加入していない住民を被保険者とする国民皆保険制度の基礎です。2

国民健康保険料は国民健康保険税という税金として納める事が多いです。詳しくはWikipediaの国民健康保険税の記事3や、freeeさんの国民健康保険料の計算方法をわかりやすく解説|知っておきたい税の基本4を読んで下さい。

沖縄県の国民健康保険料

市町村が運営しているので自治体によって金額が違います。赤字なので保険料が高いです :up:

国保、沖縄県内10市町村で保険料上昇予測 県は徴収料統一検討
http://www.okinawatimes.co.jp/articles/-/133399

沖縄戦の影響で全国と比べ前期高齢者(65~74歳)の割合が低く、前期高齢者の割合を基に算出される交付金が低いことが、国保財政の悪化につながっている。
https://ryukyushimpo.jp/news/entry-435651.html

計算方法

那覇市を例にします。以下の3つの区分の合算です。

保険税の年税額は、医療分と支援分と介護分(40歳~64歳の方)の合算額です。医療分と支援分と介護分はそれぞれ別々に計算されます。
http://www.city.naha.okinawa.jp/kakuka/kokuhotyoujyu/hokenzeinoufu.html

65歳からは介護分は掛かりませんが、介護保険料が別途掛かります(また、75歳からは国保ではなく後期高齢者医療制度に加入することになります)。

那覇市の場合はそれぞれの分について以下の3つを計算していきます。

  • 所得割: 所得×税率
  • 均等割: 加入者数×◯円
  • 平等割: 世帯あたり◯円

自治体によっては所得割、均等割、平等割の他に資産割があったりします。その場合固定資産税×税率を計算します。

実装

計算機の初期化

国保は世帯ごとに請求されるので計算機の引数で国保に加入する世帯の構成員を取ります。詳しくは擬制世帯でググってください。

class JapaneseNationalHealthInsuranceCalculator
  def initialize(household)
    @household = household
  end
end

初期化する際に引数で渡す世帯の構成員を定義してみましょう。
国保税を計算するためには以下の情報が取れる必要があります。

  • 介護分の計算: 年齢
  • 所得割の計算: 所得
  • 資産割の計算: 固定資産税額

それに加え、介護分が必要な年齢か調べるメソッドも追加しましょう

class HouseholdMember < Struct.new(:age, :income, :fixed_assets_tax)
  def long_term_care_insurance_premium?
    (40...65).cover?(age)
  end
end

これで以下のように世帯を渡して国民健康保険料の計算機を初期化できるようになりました。

household = [
  HouseholdMember.new(27, 2472120, 0),
  HouseholdMember.new(29, 0, 0),
  HouseholdMember.new(0, 0, 0)
]
calculator = JapaneseNationalHealthInsuranceCalculator.new(household)

国民健康保険料の計算

国民健康保険料の計算について、以下3つの金額の合計なので定義は簡単です。

  • 医療分
  • 支援分
  • 介護分
class JapaneseNationalHealthInsuranceCalculator
  def calculate
    medical_insurance_premium + medical_care_assistance + long_term_care_insurance_premium
  end
end

問題は自治体によって、所得割・資産割の税率や均等割・平等割の金額が変わること、資産割がある/ないが変わることです。

  • 所得割: 所得×税率
  • 均等割: 加入者数×◯円
  • 平等割: 世帯あたり◯円
  • 資産割: 固定資産税×税率

部分ごとの計算機をつくる

以下の4種類の計算機を作りましょう。

  • 所得割
  • 均等割
  • 平等割
  • 資産割

それぞれの計算機に以下の3つを計算するAPIを実装します。

  • 医療分
  • 支援分
  • 介護分

例えば所得割の場合、以下のように所得割の税率を引数で受け取るようにすると、自治体ごとに個別の計算機を作る必要がなくなるので便利でしょう。

class IncomeLevyCalculator < Struct.new(:household_member, :medical_insurance_premium_ratio, :medical_care_assistance_ratio, :long_term_care_insurance_premium_ratio)
  def medical_insurance_premium
    income * medical_insurance_premium_ratio
  end

  def medical_care_assistance
    income * medical_care_assistance_ratio
  end

  def long_term_care_insurance_premium
    if household_member.long_term_care_insurance_premium?
      income * long_term_care_insurance_ratio
    else
      0
    end
  end

  private

  def income
    [household_member.income - basic_deduction, 0].max
  end

  def basic_deduction
    330_000
  end
end

同じような感じで他の計算機も作ります。

# 均等割
class PerCapitaBasisLevyCalculator < Struct.new(:medical_insurance_premium, :medical_care_assistance, :long_term_care_insurance_premium)
end

# 平等割
class FlatLevyCalculator < Struct.new(:medical_insurance_premium, :medical_care_assistance, :long_term_care_insurance_premium)
end

# 資産割
class PropertyLevyCalculator
  def initialize(fixed_assets_tax, medical_insurance_premium_ratio, medical_care_assistance_ratio, long_term_care_insurance_premium_ratio)
    @fixed_assets_tax                       = fixed_assets_tax
    @medical_insurance_premium_ratio        = medical_insurance_premium_ratio
    @medical_care_assistance_ratio          = medical_care_assistance_ratio
    @long_term_care_insurance_premium_ratio = long_term_care_insurance_premium_ratio
  end

  def medical_insurance_premium
    @medical_insurance_premium_ratio * @fixed_assets_tax
  end

  def medical_care_assistance
    @medical_care_assistance_ratio * @fixed_assets_tax
  end

  def long_term_care_insurance_premium
    @long_term_care_insurance_ratio * @fixed_assets_tax
  end
end

計算機を組み合わせる

それぞれの市町村に必要な計算機を作ります。

例えば那覇市の場合

所得割

医療分 支援分 介護分
9.70% 1.59% 1.56%

均等割

医療分 支援分 介護分
18,200 3,300 7,700

平等割

医療分 支援分 介護分
25,400 5,300 4,600

なので以下のような組み合わせです。

calculators = [
  household.map { |household_member| IncomeLevyCalculator.new(household_member, 970/10000r, 159/10000r, 156/10000r) },
  PerCapitaBasisLevyCalculator.new(household, 18_200, 3_300, 7_700),
  FlatLevyCalculator.new(household, 25_400, 5_300, 4_600)
].flatten

国保計算機にこれらの子計算機を入れられるようにします。

class JapaneseNationalHealthInsuranceCalculator
  attr_accessor :calculators
end

calculator.calculators = calculators

子計算機を使って計算するようメソッドを定義します。

class JapaneseNationalHealthInsuranceCalculator
  def medical_insurance_premium
    calculators.sum(&:medical_insurance_premium)
  end

  def medical_care_assistance
    calculators.sum(&:medical_care_assistance)
  end

  def long_term_care_insurance_premium
    calculators.sum(&:long_term_care_insurance_premium)
  end
end

結果

puts calculator.calculate.to_i
# 337045

無事国民健康保険料が計算できました!

沖縄県の各市町村で計算してみる

資産のことを気にしなければさっきの要領で子計算機を作る処理を使いまわせます。

ググったりして以下のようなTSVのデータを用意します。自治体によってはウェブに保険料が載っていないのでとりあえず市だけ調べました。

tsv = <<TSV
那覇市   9.70%   1.59%   1.56%   18200   3300    7700    25400   5300    4600                http://www.city.naha.okinawa.jp/kakuka/kokuhotyoujyu/hokenzeinoufu.html
浦添市   8.20%   2.40%   2.40%   19000   7500    9500    17000   6000    6000                http://www.city.urasoe.lg.jp/docs/2014110102709/
南城市   6.70%   2.60%   1.90%   16700   7000    5900    18200   7000    4300                http://www.city.nanjo.okinawa.jp/life/insurance/kokuho.html
沖縄市   9.12%   2.27%   1.86%   19712   5312    5686    20919   5637    3927                https://www.city.okinawa.okinawa.jp/kurashi/365/2286
豊見城市    8.44%   2.61%   2.10%   17200   6200    6600    23200   5400    3700                http://www.city.tomigusuku.okinawa.jp/userfiles/files/health/2016bookall.pdf
宜野湾市    6.63%   2.75%   1.62%   14300   5200    3900    19500   7100    5100                http://www.city.ginowan.okinawa.jp/life/health/02/37447.html
糸満市   9.00%   1.50%   2.20%   16000   3700    6900    20000   5000    4700    30.00%  6.50%   5.10%   http://www.city.itoman.lg.jp/docs/2013020102935/
うるま市    7.70%   2.50%   2.10%   14000   6500    7200    22000   6000    6000                http://www.city.uruma.lg.jp/kurashi/122/3149/492
宮古島市    8.35%   2.10%   2%  17500   4300    5000    15500   4000    3000    30% 7%  5.8 http://www.city.miyakojima.lg.jp/kurashi/kokumin/kenkouhoken/2017-0616-1306-81.html
石垣市   8.35%   2.20%   2.20%   18300   4300    6500    16600   5500    4000    19% 5%  4.20%   http://www.city.ishigaki.okinawa.jp/home/shiminhokenbu/kenkouhoken/index.htm#p2
名護市   6.30%   2.70%   1.20%   14500   5900    4300    12500   5100    3600    20.00%  9.00%   4.00%   http://www.city.nago.okinawa.jp/4/3835.html
TSV

おもむろにこねくり回す

puts "自治体 | 国保料"
puts "--- | ---"
tsv.lines.map { |l| l.chomp.split("\t") }.each do |row|
  local_gov = row[0]
  income_lavy_ratios = row[1..3].map {|percentage| percentage.delete('.%').to_i / 10000r }
  per_capita_basis = row[4..6].map(&:to_i)
  flat = row[7..9].map(&:to_i)

  calculator.calculators = [
    household.map { |household_member| IncomeLevyCalculator.new(household_member, *income_lavy_ratios) },
    PerCapitaBasisLevyCalculator.new(household, *per_capita_basis),
    FlatLevyCalculator.new(household, *flat)
  ].flatten
  tax = calculator.calculate.to_i
  puts "[#{local_gov}](#{row[13]}) | #{tax}"
end

はい

自治体 国保料
那覇市 337045
浦添市 329564
南城市 295517
沖縄市 345615
豊見城市 335504
宜野湾市 286030
糸満市 309022
うるま市 307996
宮古島市 308751
石垣市 315893
名護市 271590

まとめ

  • Rubyを使うと国保税が計算できてべんり
  • 沖縄の国保税意外と高い

明日の記事はあっとんさんです。

コード

tsvだけ変えれば別の自治体でも使えます。5 6

class JapaneseNationalHealthInsuranceCalculator
  attr_accessor :calculators

  def initialize(household)
    @household = household
  end

  def calculate
    medical_insurance_premium + medical_care_assistance + long_term_care_insurance_premium
  end

  def medical_insurance_premium
    calculators.sum(&:medical_insurance_premium)
  end

  def medical_care_assistance
    calculators.sum(&:medical_care_assistance)
  end

  def long_term_care_insurance_premium
    calculators.sum(&:long_term_care_insurance_premium)
  end
end

class HouseholdMember < Struct.new(:age, :income, :fixed_assets_tax)
  def long_term_care_insurance_premium?
    (40...65).cover?(age)
  end
end

class IncomeLevyCalculator < Struct.new(:household_member, :medical_insurance_premium_ratio, :medical_care_assistance_ratio, :long_term_care_insurance_premium_ratio)
  def medical_insurance_premium
    income * medical_insurance_premium_ratio
  end

  def medical_care_assistance
    income * medical_care_assistance_ratio
  end

  def long_term_care_insurance_premium
    if household_member.long_term_care_insurance_premium?
      income * long_term_care_insurance_ratio
    else
      0
    end
  end

  private

  def income
    [household_member.income - basic_deduction, 0].max
  end

  def basic_deduction
    330_000
  end
end

# 均等割
class PerCapitaBasisLevyCalculator < Struct.new(:household_members, :medical_insurance_premium, :medical_care_assistance, :long_term_care_insurance_premium)
  def medical_insurance_premium
    super * household_member_num
  end

  def medical_care_assistance
    super * household_member_num
  end

  def long_term_care_insurance_premium
    super * long_term_care_insurance_premium_member_num
  end

  private

  def household_member_num
    household_members.size
  end

  def long_term_care_insurance_premium_member_num
    household_members.select(&:long_term_care_insurance_premium?).size
  end
end

# 平等割
class FlatLevyCalculator < Struct.new(:household_members, :medical_insurance_premium, :medical_care_assistance, :long_term_care_insurance_premium)
  def long_term_care_insurance_premium
    if household_members.any?(&:long_term_care_insurance_premium?)
      super
    else
      0
    end
  end
end

# 資産割
class PropertyLevyCalculator < Struct.new(:household_members, :fixed_assets_tax, :medical_insurance_premium_ratio, :medical_care_assistance_ratio, :long_term_care_insurance_premium_ratio)
  def medical_insurance_premium
    @medical_insurance_premium_ratio * @fixed_assets_tax
  end

  def medical_care_assistance
    @medical_care_assistance_ratio * @fixed_assets_tax
  end

  def long_term_care_insurance_premium
    if household_members.any?(&:long_term_care_insurance_premium?)
      @long_term_care_insurance_ratio * @fixed_assets_tax
    else
      0
    end
  end
end

household = [
  HouseholdMember.new(27, 2472120, 0),
  HouseholdMember.new(29, 0, 0),
  HouseholdMember.new(0, 0, 0)
]
calculator = JapaneseNationalHealthInsuranceCalculator.new(household)

tsv = <<TSV
那覇市   9.70%   1.59%   1.56%   18200   3300    7700    25400   5300    4600                http://www.city.naha.okinawa.jp/kakuka/kokuhotyoujyu/hokenzeinoufu.html
浦添市   8.20%   2.40%   2.40%   19000   7500    9500    17000   6000    6000                http://www.city.urasoe.lg.jp/docs/2014110102709/
南城市   6.70%   2.60%   1.90%   16700   7000    5900    18200   7000    4300                http://www.city.nanjo.okinawa.jp/life/insurance/kokuho.html
沖縄市   9.12%   2.27%   1.86%   19712   5312    5686    20919   5637    3927                https://www.city.okinawa.okinawa.jp/kurashi/365/2286
豊見城市    8.44%   2.61%   2.10%   17200   6200    6600    23200   5400    3700                http://www.city.tomigusuku.okinawa.jp/userfiles/files/health/2016bookall.pdf
宜野湾市    6.63%   2.75%   1.62%   14300   5200    3900    19500   7100    5100                http://www.city.ginowan.okinawa.jp/life/health/02/37447.html
糸満市   9.00%   1.50%   2.20%   16000   3700    6900    20000   5000    4700    30.00%  6.50%   5.10%   http://www.city.itoman.lg.jp/docs/2013020102935/
うるま市    7.70%   2.50%   2.10%   14000   6500    7200    22000   6000    6000                http://www.city.uruma.lg.jp/kurashi/122/3149/492
宮古島市    8.35%   2.10%   2%  17500   4300    5000    15500   4000    3000    30% 7%  5.8 http://www.city.miyakojima.lg.jp/kurashi/kokumin/kenkouhoken/2017-0616-1306-81.html
石垣市   8.35%   2.20%   2.20%   18300   4300    6500    16600   5500    4000    19% 5%  4.20%   http://www.city.ishigaki.okinawa.jp/home/shiminhokenbu/kenkouhoken/index.htm#p2
名護市   6.30%   2.70%   1.20%   14500   5900    4300    12500   5100    3600    20.00%  9.00%   4.00%   http://www.city.nago.okinawa.jp/4/3835.html
TSV

puts "自治体 | 国保料"
puts "--- | ---"
tsv.lines.map { |l| l.chomp.split("\t") }.each do |row|
  local_gov = row[0]
  income_lavy_ratios = row[1..3].map {|percentage| percentage.delete('.%').to_i / 10000r }
  per_capita_basis = row[4..6].map(&:to_i)
  flat = row[7..9].map(&:to_i)

  calculator.calculators = [
    household.map { |household_member| IncomeLevyCalculator.new(household_member, *income_lavy_ratios) },
    PerCapitaBasisLevyCalculator.new(household, *per_capita_basis),
    FlatLevyCalculator.new(household, *flat)
  ].flatten
  tax = calculator.calculate.to_i
  puts "[#{local_gov}](#{row[13]}) | #{tax}"
end

脚注


  1. http://www.mhlw.go.jp/houdou_kouhou/kouhou_shuppan/pdf/2015-jimu_13.pdf 

  2. http://www.mhlw.go.jp/stf/seisakunitsuite/bunya/kenkou_iryou/iryouhoken/iryouhoken01/index.html 

  3. https://ja.wikipedia.org/wiki/%E5%9B%BD%E6%B0%91%E5%81%A5%E5%BA%B7%E4%BF%9D%E9%99%BA%E7%A8%8E 

  4. https://keiei.freee.co.jp/2015/06/26/kokuho-keisan/ 

  5. 固定資産がある人はcalculators設定まわり直して下さい 

  6. 実際は10期に支払いが分かれていたり年度中に年齢が変わる場合やx円未満切り捨てなどでもっと計算が難しい