lucasalary-jp 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/lib/luca_salary/dict/code.tsv +56 -0
- data/lib/luca_salary/jp-national-tax/.gitignore +57 -0
- data/lib/luca_salary/jp-national-tax/LICENSE +674 -0
- data/lib/luca_salary/jp-national-tax/income-tax/income_kouran_2020.rb +106 -0
- data/lib/luca_salary/jp-national-tax/income_tax.rb +33 -0
- data/lib/luca_salary/jp.rb +50 -0
- data/lib/luca_salary/jp/insurance.rb +66 -0
- data/lib/luca_salary/jp/version.rb +3 -0
- metadata +114 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
require "date"
|
2
|
+
require "bigdecimal"
|
3
|
+
|
4
|
+
module JP
|
5
|
+
module IncomeTax
|
6
|
+
module Kouran2020
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def effective_date
|
11
|
+
Date.parse("2020-01-01")
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# 月額表の甲欄を適用する給与等につき、電子計算機等を使用して源泉徴収税額を計算する方法
|
16
|
+
#
|
17
|
+
def monthly_kouran (その月の社会保険料等控除後の給与等の金額, 配偶者 = false, 控除対象扶養親族の数 = 0)
|
18
|
+
|
19
|
+
b = その月の社会保険料等控除後の給与等の金額
|
20
|
+
|
21
|
+
配偶者控除の額及び扶養控除の額 = 扶養控除の額 (控除対象扶養親族の数)
|
22
|
+
配偶者控除の額及び扶養控除の額 += 配偶者控除の額 if 配偶者
|
23
|
+
|
24
|
+
課税給与所得金額 = b - 配偶者控除の額及び扶養控除の額 - 給与所得控除の額(b) - 基礎控除の額(b)
|
25
|
+
|
26
|
+
源泉徴収額 = 税額(課税給与所得金額).to_i
|
27
|
+
|
28
|
+
if 源泉徴収額 > 0
|
29
|
+
源泉徴収額
|
30
|
+
else
|
31
|
+
0
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def 給与所得控除の額 (その月の社会保険料控除後の給与等の金額)
|
38
|
+
|
39
|
+
case その月の社会保険料控除後の給与等の金額
|
40
|
+
when 0 .. 135_416
|
41
|
+
45_834
|
42
|
+
when 135_417 .. 149_999
|
43
|
+
(その月の社会保険料控除後の給与等の金額 * BigDecimal("0.4")).ceil - 8_333
|
44
|
+
when 150_000 .. 299_999
|
45
|
+
(その月の社会保険料控除後の給与等の金額 * BigDecimal("0.3")).ceil + 6_667
|
46
|
+
when 300_000 .. 549_999
|
47
|
+
(その月の社会保険料控除後の給与等の金額 * BigDecimal("0.2")).ceil + 36_667
|
48
|
+
when 550_000 .. 708_330
|
49
|
+
(その月の社会保険料控除後の給与等の金額 * BigDecimal("0.1")).ceil + 91_667
|
50
|
+
else
|
51
|
+
162_500
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def 配偶者控除の額
|
58
|
+
31_667
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def 扶養控除の額 (控除対象扶養親族の数)
|
63
|
+
31_667 * 控除対象扶養親族の数
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def 基礎控除の額 (その月の社会保険料等控除後の給与等の金額)
|
68
|
+
|
69
|
+
case その月の社会保険料等控除後の給与等の金額
|
70
|
+
when 0 .. 2_162_499
|
71
|
+
40_000
|
72
|
+
when 2_162_500 .. 2_204_166
|
73
|
+
26_667
|
74
|
+
when 2_204_167 .. 2_245_833
|
75
|
+
13_334
|
76
|
+
else
|
77
|
+
0
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def 税額 (その月の課税給与所得金額)
|
84
|
+
|
85
|
+
case その月の課税給与所得金額
|
86
|
+
when 0 .. 162_500
|
87
|
+
(その月の課税給与所得金額 * BigDecimal("0.05105")).round(0, BigDecimal::ROUND_HALF_UP)
|
88
|
+
when 162_501 .. 275_000
|
89
|
+
(その月の課税給与所得金額 * BigDecimal("0.10210")).round(0, BigDecimal::ROUND_HALF_UP) - 8_296
|
90
|
+
when 275_001 .. 579_166
|
91
|
+
(その月の課税給与所得金額 * BigDecimal("0.20420")).round(0, BigDecimal::ROUND_HALF_UP) - 36_374
|
92
|
+
when 579_001 .. 750_000
|
93
|
+
(その月の課税給与所得金額 * BigDecimal("0.23483")).round(0, BigDecimal::ROUND_HALF_UP) - 54_113
|
94
|
+
when 750_001 .. 1_500_000
|
95
|
+
(その月の課税給与所得金額 * BigDecimal("0.33693")).round(0, BigDecimal::ROUND_HALF_UP) - 130_688
|
96
|
+
when 1_500_001 .. 3_333_333
|
97
|
+
(その月の課税給与所得金額 * BigDecimal("0.40840")).round(0, BigDecimal::ROUND_HALF_UP) - 237_893
|
98
|
+
else
|
99
|
+
(その月の課税給与所得金額 * BigDecimal("0.45945")).round(0, BigDecimal::ROUND_HALF_UP) - 408_061
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "date"
|
2
|
+
Dir[File.expand_path("income-tax/income*.rb", __dir__)].each{|f| require_relative(f)}
|
3
|
+
|
4
|
+
module JP
|
5
|
+
module IncomeTax
|
6
|
+
MOD = [Kouran2020]
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def calc_kouran(pay_amount, pay_date, partner = false, dependent = 0)
|
11
|
+
responsible_module(pay_date)
|
12
|
+
.send(:monthly_kouran, pay_amount, partner, dependent)
|
13
|
+
.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
def responsible_module(date = nil)
|
17
|
+
if date.nil?
|
18
|
+
raise UndefinedDateError
|
19
|
+
elsif date.class.name == "String"
|
20
|
+
date = Date.parse(date)
|
21
|
+
end
|
22
|
+
|
23
|
+
rules = MOD.map{|mod| [mod.send(:effective_date), mod] }.filter{|a| date >= a[0]}
|
24
|
+
|
25
|
+
if rules.length > 0
|
26
|
+
rules.sort_by{|a| a[0]}.reverse!.first[1]
|
27
|
+
else
|
28
|
+
raise NoValidModuleError
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'luca_salary/jp/version'
|
2
|
+
require 'date'
|
3
|
+
require 'luca_salary'
|
4
|
+
require 'luca_salary/jp/insurance'
|
5
|
+
require 'jp_national_tax'
|
6
|
+
|
7
|
+
class LucaSalary::JP < LucaSalary::Base
|
8
|
+
def initialize(dir_path, config = nil, date = nil)
|
9
|
+
@pjdir = dir_path
|
10
|
+
@date = date
|
11
|
+
@insurance = InsuranceJP.new(@pjdir, config.dig('jp', 'area'), date)
|
12
|
+
end
|
13
|
+
|
14
|
+
# need for local dictionary loading
|
15
|
+
def self.country_path
|
16
|
+
__dir__
|
17
|
+
end
|
18
|
+
|
19
|
+
def calc_payment(profile)
|
20
|
+
{}.tap do |h|
|
21
|
+
select_code(profile, '1').each { |k, v| h[k] = v }
|
22
|
+
h['201'] = @insurance.health_insurance_salary(insurance_rank(profile))
|
23
|
+
h['202'] = @insurance.pension_salary(pension_rank(profile))
|
24
|
+
tax_base = sum_code(h, '1', income_tax_exception) - h['201'] - h['202']
|
25
|
+
h['203'] = JpNationalTax::IncomeTax.calc_kouran(tax_base, Date.today, true)
|
26
|
+
h['211'] = resident_tax(profile)
|
27
|
+
select_code(profile, '3').each { |k, v| h[k] = v }
|
28
|
+
select_code(profile, '4').each { |k, v| h[k] = v }
|
29
|
+
h.merge!(amount_by_code(h))
|
30
|
+
h['id'] = profile.dig('id')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def income_tax_exception
|
35
|
+
%w[116 118 119 11A 11B]
|
36
|
+
end
|
37
|
+
|
38
|
+
def insurance_rank(dat)
|
39
|
+
dat.dig('insurance', 'rank')
|
40
|
+
end
|
41
|
+
|
42
|
+
def pension_rank(dat)
|
43
|
+
dat.dig('pension', 'rank')
|
44
|
+
end
|
45
|
+
|
46
|
+
def resident_tax(dat)
|
47
|
+
attr = @date.month == 6 ? 'extra' : 'ordinal'
|
48
|
+
dat.dig('resident', attr)
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'date'
|
3
|
+
require 'json'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
class InsuranceJP
|
7
|
+
attr_reader :table
|
8
|
+
|
9
|
+
# load config
|
10
|
+
def initialize(dir_path, area=nil, date=nil)
|
11
|
+
@pjdir = Pathname(dir_path) + 'dict'
|
12
|
+
@area = area
|
13
|
+
@date = date
|
14
|
+
@table = load_table
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_table
|
18
|
+
file_name = @pjdir + select_active_filename
|
19
|
+
JSON.parse(File.read(file_name.to_s))
|
20
|
+
end
|
21
|
+
|
22
|
+
def health_insurance_salary(rank)
|
23
|
+
round6(select_health_insurance(rank).dig('insurance_elder_salary'))
|
24
|
+
end
|
25
|
+
|
26
|
+
def pension_salary(rank)
|
27
|
+
round6(select_pension(rank).dig('pension_salary'))
|
28
|
+
end
|
29
|
+
|
30
|
+
def select_health_insurance(rank)
|
31
|
+
@table['fee'].filter{|h| h['rank'] == rank}.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def select_pension(rank)
|
35
|
+
@table['fee'].filter{|h| h['pension_rank'] == rank}.first
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def round6(num)
|
41
|
+
BigDecimal(num).round(0, BigDecimal::ROUND_HALF_DOWN).to_i
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO: need selection logic
|
45
|
+
def select_active_filename
|
46
|
+
list = load_json
|
47
|
+
list.first[1]
|
48
|
+
end
|
49
|
+
|
50
|
+
def load_json
|
51
|
+
table_list = [].tap do |a|
|
52
|
+
open_tables do |f, name|
|
53
|
+
data = JSON.parse(f.read)
|
54
|
+
a << [Date.parse(data['effective_date']), name]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def open_tables
|
60
|
+
Dir.chdir(@pjdir.to_s) do
|
61
|
+
Dir.glob("*.json").each do |file_name|
|
62
|
+
File.open(file_name, 'r') {|f| yield(f, file_name)}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lucasalary-jp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chuma Takahiro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-10-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lucasalary
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 12.3.3
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 12.3.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
description: 'LucaSalary calculation module for Japan
|
70
|
+
|
71
|
+
'
|
72
|
+
email:
|
73
|
+
- co.chuma@gmail.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- LICENSE
|
79
|
+
- lib/luca_salary/dict/code.tsv
|
80
|
+
- lib/luca_salary/jp-national-tax/.git
|
81
|
+
- lib/luca_salary/jp-national-tax/.gitignore
|
82
|
+
- lib/luca_salary/jp-national-tax/LICENSE
|
83
|
+
- lib/luca_salary/jp-national-tax/income-tax/income_kouran_2020.rb
|
84
|
+
- lib/luca_salary/jp-national-tax/income_tax.rb
|
85
|
+
- lib/luca_salary/jp.rb
|
86
|
+
- lib/luca_salary/jp/insurance.rb
|
87
|
+
- lib/luca_salary/jp/version.rb
|
88
|
+
homepage: https://github.com/chumaltd/luca-salary-jp
|
89
|
+
licenses:
|
90
|
+
- GPL
|
91
|
+
metadata:
|
92
|
+
homepage_uri: https://github.com/chumaltd/luca-salary-jp
|
93
|
+
source_code_uri: https://github.com/chumaltd/luca-salary-jp
|
94
|
+
changelog_uri: https://github.com/chumaltd/luca-salary-jp/CHANGELOG.md
|
95
|
+
post_install_message:
|
96
|
+
rdoc_options: []
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 2.6.0
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubygems_version: 3.1.2
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: LucaSalary calculation molule for Japan
|
114
|
+
test_files: []
|