luca-jp 0.12.4 → 0.14.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 +4 -4
- data/exe/luca-jp +18 -0
- data/lib/luca/jp/sonshitsu.rb +1 -1
- data/lib/luca/jp/version.rb +1 -1
- data/lib/luca/jp.rb +2 -1
- data/lib/luca_salary/dict/code.tsv +62 -0
- data/lib/luca_salary/jp/insurance.rb +70 -0
- data/lib/luca_salary/jp/version.rb +5 -0
- data/lib/luca_salary/jp.rb +85 -0
- data/lib/luca_salary/jp_payreport.rb +248 -0
- metadata +48 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 605b45fb833509ab94115fefbcd0d94db75f5a232c5391ca6b0f3ba06b62871e
|
4
|
+
data.tar.gz: 7270ff0d48471dc3a65653f5209f5d00fd0f035c9bdc65e38f3bbf2c4d33f1c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7bba7eaa908d2e124b7ff1e7f438486106b173001b1e646d5ded0445641585dca28c41697e3fc2e3b1f93c29363d30e81574609e0e46a6157ff4c6ff397c582f
|
7
|
+
data.tar.gz: d4ca22c3cb75086398b6ec40337f44bc4a0da0bb83f41a837336d31d0cc857aa1d476f05aeef2492c4cc5c724dc8ee1cc3f41d197442639a48d5eda99cea0641
|
data/exe/luca-jp
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'optparse'
|
4
5
|
require 'luca/jp'
|
6
|
+
require 'luca_salary/jp_payreport'
|
5
7
|
|
6
8
|
class LucaCmd
|
7
9
|
def self.syouhizei(args, params)
|
@@ -54,6 +56,15 @@ class LucaCmd
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
59
|
+
module LucaSalaryCmd
|
60
|
+
class Export
|
61
|
+
def self.payreport(args = nil, _params = nil)
|
62
|
+
puts LucaSalary::JpPayreport.export(args.first)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
LucaRecord::Base.valid_project?
|
57
68
|
cmd = ARGV.shift
|
58
69
|
params = {}
|
59
70
|
|
@@ -89,6 +100,12 @@ when /urikake/
|
|
89
100
|
args = opt.parse!(ARGV)
|
90
101
|
LucaCmd.urikake(args, params)
|
91
102
|
end
|
103
|
+
when 'k', 'kyuyo', 'salary'
|
104
|
+
OptionParser.new do |opt|
|
105
|
+
opt.banner = 'Usage: luca-jp kyuyo [--export] year'
|
106
|
+
args = opt.parse(ARGV)
|
107
|
+
LucaSalaryCmd::Export.payreport(args)
|
108
|
+
end
|
92
109
|
else
|
93
110
|
puts 'Proper subcommand needed.'
|
94
111
|
puts
|
@@ -96,6 +113,7 @@ else
|
|
96
113
|
puts ' h[oujinzei]: 法人税の計算'
|
97
114
|
puts ' s[youhizei]: 消費税の計算'
|
98
115
|
puts ' c[hihouzei]: 地方税の計算'
|
116
|
+
puts ' k[yuyo]: 給与報告(所得税)の計算'
|
99
117
|
puts ' urikake: 勘定科目内訳明細書の売掛金リスト(CSV)'
|
100
118
|
exit 1
|
101
119
|
end
|
data/lib/luca/jp/sonshitsu.rb
CHANGED
@@ -37,7 +37,7 @@ module Luca
|
|
37
37
|
#
|
38
38
|
def self.load(this_year)
|
39
39
|
records = if File.exist?(record_file)
|
40
|
-
YAML.
|
40
|
+
YAML.safe_load(File.read(record_file), permitted_classes: [Date])
|
41
41
|
.filter { |record| record['start_date'] > this_year.prev_year(11) && record['end_date'] < this_year }
|
42
42
|
.sort { |a, b| a['start_date'] <=> b['start_date'] }
|
43
43
|
else
|
data/lib/luca/jp/version.rb
CHANGED
data/lib/luca/jp.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'date'
|
3
4
|
require 'luca/jp/version'
|
4
5
|
require 'luca_support/config'
|
5
6
|
|
@@ -18,7 +19,7 @@ module Luca
|
|
18
19
|
end
|
19
20
|
|
20
21
|
EX_CONF = begin
|
21
|
-
YAML.
|
22
|
+
YAML.safe_load(File.read(Pathname(LucaSupport::PJDIR) / 'config-lucajp.yml'), permitted_classes: [Date])
|
22
23
|
rescue Errno::ENOENT
|
23
24
|
nil
|
24
25
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
code label acct_label
|
2
|
+
1 総支給額
|
3
|
+
101 役員報酬 役員報酬
|
4
|
+
102 基本給 給料手当
|
5
|
+
103 残業手当 給料手当
|
6
|
+
104 深夜手当 給料手当
|
7
|
+
105 休日手当 給料手当
|
8
|
+
106 遅刻早退 給料手当
|
9
|
+
107 欠勤控除 給料手当
|
10
|
+
108 reserved
|
11
|
+
109 reserved
|
12
|
+
10A reserved
|
13
|
+
10B reserved
|
14
|
+
10C reserved
|
15
|
+
10D reserved
|
16
|
+
10E reserved
|
17
|
+
10F reserved
|
18
|
+
111 役職手当 給料手当
|
19
|
+
112 家族手当 給料手当
|
20
|
+
113 住宅手当 給料手当
|
21
|
+
114 役職手当 給料手当
|
22
|
+
115 資格手当 給料手当
|
23
|
+
116 通勤手当(非課税) 給料手当
|
24
|
+
117 通勤手当(課税) 給料手当
|
25
|
+
118 旅費手当(非課税) 給料手当
|
26
|
+
119 宿日直料(非課税) 給料手当
|
27
|
+
11A 夜食代(非課税) 給料手当
|
28
|
+
11B 見舞金(非課税) 給料手当
|
29
|
+
11C reserved
|
30
|
+
11D reserved
|
31
|
+
11E reserved
|
32
|
+
11F reserved
|
33
|
+
121 役員賞与 役員賞与
|
34
|
+
122 賞与 賞与
|
35
|
+
123 出張旅費 給料手当
|
36
|
+
124 退職手当 退職金
|
37
|
+
2 税・保険料控除額
|
38
|
+
201 健康保険料 法定福利費
|
39
|
+
202 厚生年金保険料 法定福利費
|
40
|
+
203 所得税 所得税源泉給与
|
41
|
+
204 雇用保険料 預り金
|
42
|
+
205 介護保険料 法定福利費
|
43
|
+
211 住民税 住民税
|
44
|
+
3 その他控除額
|
45
|
+
311 社宅本人負担分 雑収入
|
46
|
+
3A1 年末調整不足分 預り金
|
47
|
+
4 加算額
|
48
|
+
4A1 年末調整還付 預り金
|
49
|
+
5 差引支給金額 未払費用
|
50
|
+
901 給与所得控除後の給与等の金額
|
51
|
+
911 基礎控除
|
52
|
+
912 社会保険料控除
|
53
|
+
913 生命保険料控除
|
54
|
+
914 地震保険料控除
|
55
|
+
915 小規模企業共済等掛金控除
|
56
|
+
916 配偶者控除
|
57
|
+
917 配偶者特別控除
|
58
|
+
918 扶養控除
|
59
|
+
919 住宅借入金等特別控除
|
60
|
+
920 障害者等の控除
|
61
|
+
941 課税給与所得金額
|
62
|
+
961 年調年税額
|
@@ -0,0 +1,70 @@
|
|
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
|
+
def select_active_filename
|
45
|
+
list_json
|
46
|
+
.filter { |tbl| tbl[0] <= @date }
|
47
|
+
.max { |a, b| a[0] <=> b[0] }
|
48
|
+
.last
|
49
|
+
end
|
50
|
+
|
51
|
+
def list_json
|
52
|
+
table_list = [].tap do |a|
|
53
|
+
open_tables do |f, name|
|
54
|
+
data = JSON.parse(f.read)
|
55
|
+
next if @area && data['area'] != @area
|
56
|
+
|
57
|
+
a << [Date.parse(data['effective_date']), name]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# TODO: Limit only to pension tables.
|
63
|
+
def open_tables
|
64
|
+
Dir.chdir(@pjdir.to_s) do
|
65
|
+
Dir.glob("*.json").each do |file_name|
|
66
|
+
File.open(file_name, 'r') {|f| yield(f, file_name)}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,85 @@
|
|
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 = self.class.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 self.year_total(payment, date)
|
35
|
+
payment.tap do |p|
|
36
|
+
p['911'] = JpNationalTax::IncomeTax.basic_deduction(p['1'], date)
|
37
|
+
p['916'] = partner_deduction(p['1'])
|
38
|
+
p['912'] = ['201', '202', '204', '205'].map{ |cd| p[cd] }.compact.sum
|
39
|
+
p['901'] = JpNationalTax::IncomeTax.year_salary_taxable(p['1'], date)
|
40
|
+
p['941'] = p['901'] - p['911'] - p['912'] - p['916']
|
41
|
+
p['961'] = JpNationalTax::IncomeTax.year_tax(p['941'], date)
|
42
|
+
diff = p['961'] - p['203']
|
43
|
+
if diff.positive?
|
44
|
+
p['3A1'] = diff
|
45
|
+
p['4A1'] = BigDecimal('0')
|
46
|
+
else
|
47
|
+
p['4A1'] = diff * -1
|
48
|
+
p['3A1'] = BigDecimal('0')
|
49
|
+
end
|
50
|
+
p.delete '3'
|
51
|
+
p.delete '4'
|
52
|
+
p['3'] = sum_code(p, '3')
|
53
|
+
p['4'] = sum_code(p, '4')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.partner_deduction(income)
|
58
|
+
if income <= 9_000_000
|
59
|
+
380_000
|
60
|
+
elsif income <= 9_500_000
|
61
|
+
260_000
|
62
|
+
elsif income <= 10_000_000
|
63
|
+
130_000
|
64
|
+
else
|
65
|
+
0
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def income_tax_exception
|
70
|
+
%w[116 118 119 11A 11B]
|
71
|
+
end
|
72
|
+
|
73
|
+
def insurance_rank(dat)
|
74
|
+
dat.dig('insurance', 'rank')
|
75
|
+
end
|
76
|
+
|
77
|
+
def pension_rank(dat)
|
78
|
+
dat.dig('pension', 'rank')
|
79
|
+
end
|
80
|
+
|
81
|
+
def resident_tax(dat)
|
82
|
+
attr = @date.month == 6 ? 'extra' : 'ordinal'
|
83
|
+
dat.dig('resident', attr)
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'luca_salary'
|
3
|
+
require 'luca_support/config'
|
4
|
+
require 'csv'
|
5
|
+
require 'open3'
|
6
|
+
|
7
|
+
module LucaSalary
|
8
|
+
class JpPayreport < LucaSalary::Base
|
9
|
+
|
10
|
+
def self.export(year)
|
11
|
+
if !system("uconv --version > /dev/null")
|
12
|
+
exit 1 # 半角カナ必須
|
13
|
+
end
|
14
|
+
|
15
|
+
slips = LucaSalary::Total.new(year).slips
|
16
|
+
company = set_company(year.to_i)
|
17
|
+
CSV.generate() do |csv|
|
18
|
+
slips.each do |s|
|
19
|
+
csv << 給与支払報告明細行(LucaSupport::Code.readable(s), company, year.to_i)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO: extract effective field
|
25
|
+
def self.set_company(year)
|
26
|
+
{}.tap do |h|
|
27
|
+
h['name'] = CONFIG.dig('company', 'name')
|
28
|
+
h['address'] = CONFIG.dig('company', 'address')
|
29
|
+
h['address2'] = CONFIG.dig('company', 'address2')
|
30
|
+
h['tel'] = CONFIG.dig('company', 'tel')
|
31
|
+
h['tax_id'] = CONFIG.dig('company', 'tax_id')
|
32
|
+
|
33
|
+
raise "会社名、住所の設定は必須" if h['name'].nil? or h['address'].nil?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def 給与支払報告明細行(slip, company, year)
|
42
|
+
[
|
43
|
+
315, # 法定資料の種類
|
44
|
+
提出義務者(company),
|
45
|
+
0, # 提出区分(新規0, 追加1, 訂正2, 取消3)
|
46
|
+
和暦(Date.new(year, 12, -1))[1], # 年分
|
47
|
+
支払を受ける者(slip['profile']),
|
48
|
+
支払(slip, year),
|
49
|
+
支払を受ける者の詳細(slip, year),
|
50
|
+
company['tax_id'], # 法人番号
|
51
|
+
支払を受ける者の扶養情報(slip['profile'], year),
|
52
|
+
slip['911'], # 基礎控除の額
|
53
|
+
nil, # 所得金額調整控除額 TODO: 未実装 措法41の3の3
|
54
|
+
nil, # ひとり親
|
55
|
+
提出先判定(slip), # 必須:作成区分(国税のみ0, 地方のみ1, 両方2)
|
56
|
+
].flatten
|
57
|
+
end
|
58
|
+
|
59
|
+
def 提出義務者(company)
|
60
|
+
[
|
61
|
+
nil, # 整理番号1
|
62
|
+
nil, # 本支店等区分番号
|
63
|
+
['address', 'address2'].map { |attr| company[attr] }
|
64
|
+
.compact.join(' '), # 必須:住所又は所在地
|
65
|
+
company['name'], # 必須:氏名又は名称
|
66
|
+
company['tel'], # 電話番号
|
67
|
+
nil, # 整理番号2
|
68
|
+
nil, # 提出者の住所(省略する)
|
69
|
+
nil, # 提出者の氏名(省略する)
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def 支払を受ける者(profile)
|
74
|
+
[
|
75
|
+
['address', 'address2'].map { |attr| profile[attr] }
|
76
|
+
.compact.join(' '), # 必須:住所又は居所
|
77
|
+
nil, # 国外住所表示(国内は"0"、国外は"1")
|
78
|
+
profile['name'], # 必須:氏名
|
79
|
+
nil, # 役職名
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
def 支払(slip, year)
|
84
|
+
配偶者控除等 = [slip['916'], slip['917']].compact.sum
|
85
|
+
[
|
86
|
+
'給料', # 種別
|
87
|
+
slip['1'], # 支払金額
|
88
|
+
nil, # 未払金額
|
89
|
+
slip['901'], # 給与所得控除後の給与等の金額
|
90
|
+
slip['901'] - slip['941'], # 所得控除の額の金額
|
91
|
+
slip['961'], # 源泉徴収税額
|
92
|
+
nil, # 未徴収税額
|
93
|
+
配偶者控除等 > 0 ? 1 : 2, # 控除対象配偶者の有無 TODO: 従たる給与
|
94
|
+
老人控除対象配偶者(slip.dig('profile', 'spouse'), year),
|
95
|
+
配偶者控除等, # 配偶者控除の額
|
96
|
+
nil, # 控除対象扶養親族の数 特定 主
|
97
|
+
nil, # 控除対象扶養親族の数 特定 従
|
98
|
+
nil, # 控除対象扶養親族の数 老人 主
|
99
|
+
nil, # 控除対象扶養親族の数 老人 上の内訳
|
100
|
+
nil, # 控除対象扶養親族の数 老人 従
|
101
|
+
nil, # 控除対象扶養親族の数 その他 主
|
102
|
+
nil, # 控除対象扶養親族の数 その他 従
|
103
|
+
nil, # 障害者の数 特別障害者
|
104
|
+
nil, # 障害者の数 上の内訳 NOTE: 同居・同一生計
|
105
|
+
nil, # 障害者の数 その他
|
106
|
+
slip['912'], # 社会保険料等の額
|
107
|
+
nil, # 上の内訳 NOTE: 小規模企業共済等掛金
|
108
|
+
]
|
109
|
+
end
|
110
|
+
|
111
|
+
def 支払を受ける者の詳細(slip, year)
|
112
|
+
birth = if slip.dig('profile', 'birth_date').is_a?(String)
|
113
|
+
Date.parse(slip.dig('profile', 'birth_date'))
|
114
|
+
else
|
115
|
+
slip.dig('profile', 'birth_date')
|
116
|
+
end
|
117
|
+
生年月日 = 和暦(birth)
|
118
|
+
扶養対象 = 扶養親族分類(slip.dig('profile', 'family'), year)
|
119
|
+
|
120
|
+
[
|
121
|
+
nil, # 生命保険料の控除額
|
122
|
+
nil, # 地震保険料の控除額
|
123
|
+
nil, # 住宅借入金等特別控除等の額
|
124
|
+
nil, # 旧個人年金保険料の額
|
125
|
+
slip.dig('spouse', 'income'), # 配偶者の合計所得
|
126
|
+
nil, # 旧長期損害保険料の額
|
127
|
+
生年月日[0], # 必須:受給者の生年月日 元号
|
128
|
+
生年月日[1], # 必須:受給者の生年月日 年
|
129
|
+
生年月日[2], # 必須:受給者の生年月日 月
|
130
|
+
生年月日[3], # 必須:受給者の生年月日 日
|
131
|
+
nil, # 夫あり(省略する)
|
132
|
+
birth.next_year(18) < Date.new(year, 12, -1) ? 0 : 1, # 未成年者
|
133
|
+
nil, # 乙欄適用
|
134
|
+
nil, # 本人が特別障害者
|
135
|
+
nil, # 本人がその他障害者
|
136
|
+
nil, # 老年者(省略する)
|
137
|
+
nil, # 寡婦
|
138
|
+
nil, # 寡夫(省略する)
|
139
|
+
Array.new(35), # col90まで未実装
|
140
|
+
扶養対象['16才未満'].length,
|
141
|
+
nil, # 国民年金保険料等の額
|
142
|
+
nil, # 非居住者である親族の数
|
143
|
+
]
|
144
|
+
end
|
145
|
+
|
146
|
+
def 支払を受ける者の扶養情報(profile, year)
|
147
|
+
扶養対象 = 扶養親族分類(profile['family'], year)
|
148
|
+
|
149
|
+
[
|
150
|
+
profile['tax_id'], # 個人番号
|
151
|
+
profile.dig('spouse', 'katakana'), # 控除対象配偶者カナ
|
152
|
+
profile.dig('spouse', 'name'), # 控除対象配偶者 氏名
|
153
|
+
profile.dig('spouse') ? '00' : nil, # 控除対象配偶者 区分 TODO: 非居住者(01)の設定
|
154
|
+
profile.dig('spouse', 'tax_id'), # 控除対象配偶者 個人番号
|
155
|
+
[0, 1, 2, 3].map { |i|
|
156
|
+
[
|
157
|
+
扶養対象.dig('16才以上', i, 'katakana'), # カナ
|
158
|
+
扶養対象.dig('16才以上', i, 'name'), # 氏名
|
159
|
+
扶養対象.dig('16才以上', i) ? '00' : nil, # 区分 TODO: 非居住者(01)の設定
|
160
|
+
扶養対象.dig('16才以上', i, 'tax_id'), # 個人番号
|
161
|
+
]
|
162
|
+
},
|
163
|
+
[0, 1, 2, 3].map { |i|
|
164
|
+
[
|
165
|
+
扶養対象.dig('16才未満', i, 'katakana'), # カナ
|
166
|
+
扶養対象.dig('16才未満', i, 'name'), # 氏名
|
167
|
+
扶養対象.dig('16才未満', i) ? '00' : nil, # 区分 TODO: 非居住者(01)の設定
|
168
|
+
扶養対象.dig('16才未満', i, 'tax_id'), # 個人番号
|
169
|
+
]
|
170
|
+
},
|
171
|
+
Array(扶養対象.dig('16才以上'))[4..]&.map{ |p| "(#{p['tax_id']})#{p['name']}" }&.join(' '), # 5人目以降
|
172
|
+
Array(扶養対象.dig('16才未満'))[4..]&.map{ |p| "(#{p['tax_id']})#{p['name']}" }&.join(' '), # 5人目以降
|
173
|
+
nil, # 普通徴収
|
174
|
+
nil, # 青色専従者
|
175
|
+
nil, # 条約免除
|
176
|
+
半角変換(profile['katakana']), # 必須:支払を受ける者のフリガナ(半角)
|
177
|
+
nil, # 需給者番号
|
178
|
+
profile.dig('resident', 'area_code'), # 必須:提出先市町村コード
|
179
|
+
profile.dig('resident', 'tax_id'), # 指定番号
|
180
|
+
]
|
181
|
+
end
|
182
|
+
|
183
|
+
# https://www.nta.go.jp/taxes/shiraberu/taxanswer/hotei/7411.htm
|
184
|
+
# TODO: 役員・弁護士の考慮
|
185
|
+
def 提出先判定(slip)
|
186
|
+
case slip['1']
|
187
|
+
when 0 .. 5_000_000
|
188
|
+
1
|
189
|
+
else
|
190
|
+
2
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def 老人控除対象配偶者(spouse, year)
|
195
|
+
return nil if spouse.nil?
|
196
|
+
date = spouse['birth_date']
|
197
|
+
return 0 if date.nil?
|
198
|
+
|
199
|
+
date = Date.parse(date) if date.is_a?(String)
|
200
|
+
date.next_year(70) < Date.new(year, 12, -1) ? 1 : 0
|
201
|
+
end
|
202
|
+
|
203
|
+
def 扶養親族分類(family, year)
|
204
|
+
return {} if family.nil?
|
205
|
+
|
206
|
+
{ '16才以上' => [], '16才未満' => [] }.tap do |result|
|
207
|
+
family.each do |p|
|
208
|
+
if !p['birth_date']
|
209
|
+
result['16才以上'] << p
|
210
|
+
else
|
211
|
+
date = p['birth_date']
|
212
|
+
date = Date.parse(date) if date.is_a?(String)
|
213
|
+
if date.next_year(16) < Date.new(year, 12, -1)
|
214
|
+
result['16才以上'] << p
|
215
|
+
else
|
216
|
+
result['16才未満'] << p
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def 和暦(date)
|
224
|
+
return [nil, nil, nil, nil] if date.nil?
|
225
|
+
|
226
|
+
date = Date.parse(date) if date.is_a?(String)
|
227
|
+
case date
|
228
|
+
when Date.new(0, 1, 1) .. Date.new(1868, 10, 22)
|
229
|
+
raise "Not supported before 明治"
|
230
|
+
when Date.new(1868, 10, 23) .. Date.new(1912, 7, 29)
|
231
|
+
[3, format("%02d", date.year - 1867), format("%02d", date.month), format("%02d", date.day)]
|
232
|
+
when Date.new(1912, 7, 30) .. Date.new(1926, 12, 24)
|
233
|
+
[2, format("%02d", date.year - 1911), format("%02d", date.month), format("%02d", date.day)]
|
234
|
+
when Date.new(1926, 12, 25) .. Date.new(1989, 1, 7)
|
235
|
+
[1, format("%02d", date.year - 1925), format("%02d", date.month), format("%02d", date.day)]
|
236
|
+
when Date.new(1989, 1, 8) .. Date.new(2019, 4, 30)
|
237
|
+
[4, format("%02d", date.year - 1988), format("%02d", date.month), format("%02d", date.day)]
|
238
|
+
else
|
239
|
+
[5, format("%02d", date.year - 2018), format("%02d", date.month), format("%02d", date.day)]
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def 半角変換(str)
|
244
|
+
return nil if str.nil? or str.empty?
|
245
|
+
|
246
|
+
result, _e, _s = Open3.capture3("uconv -x 'Fullwidth-Halfwidth'", stdin_data: str)
|
247
|
+
result
|
248
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: luca-jp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lucabook
|
@@ -25,19 +25,47 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.4'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: lucasalary
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
33
|
+
version: 0.1.26
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.26
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: jp-national-tax
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.1.3
|
48
|
+
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
54
|
+
version: 0.1.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.3'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: minitest
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,13 +147,19 @@ files:
|
|
119
147
|
- lib/luca/jp/urikake.rb
|
120
148
|
- lib/luca/jp/util.rb
|
121
149
|
- lib/luca/jp/version.rb
|
122
|
-
|
150
|
+
- lib/luca_salary/dict/code.tsv
|
151
|
+
- lib/luca_salary/jp.rb
|
152
|
+
- lib/luca_salary/jp/insurance.rb
|
153
|
+
- lib/luca_salary/jp/version.rb
|
154
|
+
- lib/luca_salary/jp_payreport.rb
|
155
|
+
homepage: https://github.com/chumaltd/luca-jp
|
123
156
|
licenses:
|
124
157
|
- GPL
|
125
158
|
metadata:
|
126
|
-
homepage_uri: https://github.com/chumaltd/luca-jp
|
127
|
-
source_code_uri: https://github.com/chumaltd/luca-jp
|
128
|
-
|
159
|
+
homepage_uri: https://github.com/chumaltd/luca-jp
|
160
|
+
source_code_uri: https://github.com/chumaltd/luca-jp
|
161
|
+
changelog_uri: https://github.com/chumaltd/luca-jp/CHANGELOG.md
|
162
|
+
post_install_message:
|
129
163
|
rdoc_options: []
|
130
164
|
require_paths:
|
131
165
|
- lib
|
@@ -133,15 +167,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
133
167
|
requirements:
|
134
168
|
- - ">="
|
135
169
|
- !ruby/object:Gem::Version
|
136
|
-
version: 2.
|
170
|
+
version: 2.7.0
|
137
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
172
|
requirements:
|
139
173
|
- - ">="
|
140
174
|
- !ruby/object:Gem::Version
|
141
175
|
version: '0'
|
142
176
|
requirements: []
|
143
|
-
rubygems_version: 3.
|
144
|
-
signing_key:
|
177
|
+
rubygems_version: 3.3.5
|
178
|
+
signing_key:
|
145
179
|
specification_version: 4
|
146
180
|
summary: JP tax extension for Luca
|
147
181
|
test_files: []
|