jp-national-tax 0.1.4 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34f7e3a70f29027703ea652bde0cdb5a60dfa40aed3461114fb401898562f74e
4
- data.tar.gz: a2878e533db8d5f04467dee5e89bae243c8ef141e4e864589e2ae36ea2188fdc
3
+ metadata.gz: 6076885061229cb2f1952fca326bcf9b2da7f261b424896ed0df768e5e84d7c4
4
+ data.tar.gz: f78a323d3d29ff7e9a2f91be73f32890e9be281f460abbffd40f6ba551fdaed8
5
5
  SHA512:
6
- metadata.gz: f992aeb909c4105bfe0ccd353cabd76fcb9403d2331cb06d969cc6fbf0ecac158800be544f14e2152f6fa0544fd90c8e0a996f5d40805faf899f1d4768919dce
7
- data.tar.gz: d68a46393f88546a73a054475090438c837484773e35e82205421a6b67e9a014fd0f1991cddff1a6e70d7d9c1a6dbf5b298744f689cf58bed968b00008bf6d7e
6
+ metadata.gz: 5498f8aa0d73407e46db6ea634515b0f43ec12a388bfc67241eb488c8eb66ce09140b565c5b56860426dacdde6306d52bdfe763e9214ce2656ba3a95290a8c0d
7
+ data.tar.gz: 84cf32d1332800ee51381c40a768daa44c6e54479b936dd1b652c592e236c646607b5aa77109fe26e0bde6cea2f442197e84f6b726078f992976e48477f66847
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 0.3.0
2
+
3
+ * 年末調整(2025年, 2027年)の関数を実装
4
+ * 源泉徴収甲欄(2026年)の関数を実装
5
+
6
+
7
+ ## 0.2.0
8
+
9
+ * eTax仕様のXML構造設計書を解析するツールを追加
10
+
11
+
1
12
  ## 0.1.1
2
13
 
3
14
  * 年末調整(2020年)の関数を実装
@@ -85,19 +85,19 @@ module JpNationalTax
85
85
 
86
86
  case その月の課税給与所得金額
87
87
  when 0 .. 162_500
88
- (その月の課税給与所得金額 * BigDecimal("0.05105")).round(0, BigDecimal::ROUND_HALF_UP)
88
+ (その月の課税給与所得金額 * BigDecimal("0.05105")).round(-1, BigDecimal::ROUND_HALF_UP)
89
89
  when 162_501 .. 275_000
90
- (その月の課税給与所得金額 * BigDecimal("0.10210")).round(0, BigDecimal::ROUND_HALF_UP) - 8_296
90
+ (その月の課税給与所得金額 * BigDecimal("0.10210") - 8_296).round(-1, BigDecimal::ROUND_HALF_UP)
91
91
  when 275_001 .. 579_166
92
- (その月の課税給与所得金額 * BigDecimal("0.20420")).round(0, BigDecimal::ROUND_HALF_UP) - 36_374
92
+ (その月の課税給与所得金額 * BigDecimal("0.20420") - 36_374).round(-1, BigDecimal::ROUND_HALF_UP)
93
93
  when 579_001 .. 750_000
94
- (その月の課税給与所得金額 * BigDecimal("0.23483")).round(0, BigDecimal::ROUND_HALF_UP) - 54_113
94
+ (その月の課税給与所得金額 * BigDecimal("0.23483") - 54_113).round(-1, BigDecimal::ROUND_HALF_UP)
95
95
  when 750_001 .. 1_500_000
96
- (その月の課税給与所得金額 * BigDecimal("0.33693")).round(0, BigDecimal::ROUND_HALF_UP) - 130_688
96
+ (その月の課税給与所得金額 * BigDecimal("0.33693") - 130_688).round(-1, BigDecimal::ROUND_HALF_UP)
97
97
  when 1_500_001 .. 3_333_333
98
- (その月の課税給与所得金額 * BigDecimal("0.40840")).round(0, BigDecimal::ROUND_HALF_UP) - 237_893
98
+ (その月の課税給与所得金額 * BigDecimal("0.40840") - 237_893).round(-1, BigDecimal::ROUND_HALF_UP)
99
99
  else
100
- (その月の課税給与所得金額 * BigDecimal("0.45945")).round(0, BigDecimal::ROUND_HALF_UP) - 408_061
100
+ (その月の課税給与所得金額 * BigDecimal("0.45945") - 408_061).round(-1, BigDecimal::ROUND_HALF_UP)
101
101
  end
102
102
 
103
103
  end
@@ -0,0 +1,107 @@
1
+ # coding: utf-8
2
+ require "date"
3
+ require "bigdecimal"
4
+
5
+ module JpNationalTax
6
+ module IncomeTax
7
+ module Kouran2026
8
+
9
+ module_function
10
+
11
+ def effective_date
12
+ Date.parse("2026-01-01")
13
+ end
14
+
15
+ #
16
+ # 月額表の甲欄を適用する給与等につき、電子計算機等を使用して源泉徴収税額を計算する方法
17
+ #
18
+ def monthly_kouran (その月の社会保険料等控除後の給与等の金額, 配偶者 = false, 控除対象扶養親族の数 = 0)
19
+
20
+ b = その月の社会保険料等控除後の給与等の金額
21
+
22
+ 配偶者控除の額及び扶養控除の額 = 扶養控除の額 (控除対象扶養親族の数)
23
+ 配偶者控除の額及び扶養控除の額 += 配偶者控除の額 if 配偶者
24
+
25
+ 課税給与所得金額 = b - 配偶者控除の額及び扶養控除の額 - 給与所得控除の額(b) - 基礎控除の額(b)
26
+
27
+ 源泉徴収額 = 税額(課税給与所得金額).to_i
28
+
29
+ if 源泉徴収額 > 0
30
+ 源泉徴収額
31
+ else
32
+ 0
33
+ end
34
+
35
+ end
36
+
37
+
38
+ def 給与所得控除の額 (その月の社会保険料控除後の給与等の金額)
39
+
40
+ case その月の社会保険料控除後の給与等の金額
41
+ when 0 .. 158_333
42
+ 54_167
43
+ when 158_334 .. 299_999
44
+ (その月の社会保険料控除後の給与等の金額 * BigDecimal("0.3")).ceil + 6_667
45
+ when 300_000 .. 549_999
46
+ (その月の社会保険料控除後の給与等の金額 * BigDecimal("0.2")).ceil + 36_667
47
+ when 550_000 .. 708_330
48
+ (その月の社会保険料控除後の給与等の金額 * BigDecimal("0.1")).ceil + 91_667
49
+ else
50
+ 162_500
51
+ end
52
+
53
+ end
54
+
55
+
56
+ def 配偶者控除の額
57
+ 31_667
58
+ end
59
+
60
+
61
+ def 扶養控除の額 (控除対象扶養親族の数)
62
+ 31_667 * 控除対象扶養親族の数
63
+ end
64
+
65
+
66
+ def 基礎控除の額 (その月の社会保険料等控除後の給与等の金額)
67
+
68
+ case その月の社会保険料等控除後の給与等の金額
69
+ when 0 .. 2_120_833
70
+ 48_334
71
+ when 2_120_834 .. 2_162_499
72
+ 40_000
73
+ when 2_162_500 .. 2_204_166
74
+ 26_667
75
+ when 2_204_167 .. 2_245_833
76
+ 13_334
77
+ else
78
+ 0
79
+ end
80
+
81
+ end
82
+
83
+
84
+ def 税額 (その月の課税給与所得金額)
85
+
86
+ case その月の課税給与所得金額
87
+ when 0 .. 162_500
88
+ (その月の課税給与所得金額 * BigDecimal("0.05105")).round(-1, BigDecimal::ROUND_HALF_UP)
89
+ when 162_501 .. 275_000
90
+ (その月の課税給与所得金額 * BigDecimal("0.10210") - 8_296).round(-1, BigDecimal::ROUND_HALF_UP)
91
+ when 275_001 .. 579_166
92
+ (その月の課税給与所得金額 * BigDecimal("0.20420") - 36_374).round(-1, BigDecimal::ROUND_HALF_UP)
93
+ when 579_001 .. 750_000
94
+ (その月の課税給与所得金額 * BigDecimal("0.23483") - 54_113).round(-1, BigDecimal::ROUND_HALF_UP)
95
+ when 750_001 .. 1_500_000
96
+ (その月の課税給与所得金額 * BigDecimal("0.33693") - 130_688).round(-1, BigDecimal::ROUND_HALF_UP)
97
+ when 1_500_001 .. 3_333_333
98
+ (その月の課税給与所得金額 * BigDecimal("0.40840") - 237_893).round(-1, BigDecimal::ROUND_HALF_UP)
99
+ else
100
+ (その月の課税給与所得金額 * BigDecimal("0.45945") - 408_061).round(-1, BigDecimal::ROUND_HALF_UP)
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,235 @@
1
+ # coding: utf-8
2
+ require "date"
3
+ require "bigdecimal"
4
+
5
+ module JpNationalTax #:nodoc:
6
+ module IncomeTax #:nodoc:
7
+ #
8
+ # https://www.nta.go.jp/publication/pamph/gensen/nencho2025/pdf/204.pdf
9
+ #
10
+ module Nenmatsu2025
11
+
12
+ module_function
13
+
14
+ def effective_date
15
+ Date.parse("2025-12-01")
16
+ end
17
+
18
+ # 電子計算機等による年末調整
19
+ #
20
+ def 年調給与額(給与の総額)
21
+ case 給与の総額
22
+ when 1_900_000 .. 6_599_999
23
+ 階差 = 4_000
24
+ 同一階差の最小値 = 1_900_000
25
+ 給与の総額 - ((給与の総額 - 同一階差の最小値) % 階差)
26
+ else
27
+ 給与の総額
28
+ end
29
+ end
30
+
31
+ # 電子計算機等による年末調整
32
+ #
33
+ def 給与所得控除後の給与等の金額(年調給与額)
34
+ case 年調給与額
35
+ when 0 .. 650_999
36
+ 0
37
+ when 651_000 .. 1_899_999
38
+ 年調給与額 - 650_000
39
+ when 1_900_000 .. 3_599_999
40
+ (年調給与額 * BigDecimal('0.7') + 80_000).floor
41
+ when 3_600_000 .. 6_599_999
42
+ (年調給与額 * BigDecimal('0.8') - 440_000).floor
43
+ when 6_600_000 .. 8_499_999
44
+ (年調給与額 * BigDecimal('0.9') - 1_100_000).floor
45
+ when 8_500_000 .. 20_000_000
46
+ 年調給与額 - 1_950_000
47
+ else
48
+ STDERR.puts '年末調整の対象となりません'
49
+ 年調給与額 - 1_950_000
50
+ end
51
+ end
52
+
53
+ # https://www.nta.go.jp/taxes/shiraberu/taxanswer/shotoku/1199.htm
54
+ #
55
+ def 基礎控除額(所得金額)
56
+ case 所得金額
57
+ when 0 .. 1_320_000
58
+ 950_000
59
+ when 1_320_001 .. 3_360_000
60
+ 880_000
61
+ when 3_360_001 .. 4_890_000
62
+ 680_000
63
+ when 4_890_001 .. 6_550_000
64
+ 630_000
65
+ when 6_550_001 .. 23_500_000
66
+ 580_000
67
+ when 23_500_001 .. 24_000_000
68
+ 480_000
69
+ when 24_000_001 .. 24_500_000
70
+ 320_000
71
+ when 24_500_001 .. 25_000_000
72
+ 160_000
73
+ else
74
+ 0
75
+ end
76
+ end
77
+
78
+ def 扶養控除の額(生年月日, 申告年, 所得金額 = 0, 同居: nil)
79
+ return 0 if 生年月日.nil?
80
+
81
+ 基準日 = Date.new(申告年, 12, 31)
82
+ if 生年月日 > 基準日.prev_year(16)
83
+ 0
84
+ elsif 生年月日 <= 基準日.prev_year(70)
85
+ return 0 if 所得金額 > 580_000
86
+ 同居 ? 580_000 : 480_000 # 老人扶養親族
87
+ elsif 生年月日 <= 基準日.prev_year(19) and 生年月日 > 基準日.prev_year(23)
88
+ 特定親族特別控除額(所得金額)
89
+ else
90
+ 所得金額 > 580_000 ? 0 : 380_000
91
+ end
92
+ end
93
+
94
+ def 配偶者特別控除の金額(所得金額, 配偶者の所得金額, 配偶者の生年月日: nil, 申告年: nil)
95
+ return 0 if 所得金額 > 10_000_000
96
+ return 0 if 配偶者の所得金額 > 1_330_000
97
+
98
+ 老人控除対象 = if 申告年 and 配偶者の生年月日
99
+ 基準日 = Date.new(申告年, 12, 31)
100
+ 配偶者の生年月日 <= 基準日.prev_year(70)
101
+ else
102
+ false
103
+ end
104
+ if 所得金額 <= 9_000_000
105
+ case 配偶者の所得金額
106
+ when 0 .. 580_000 # 配偶者控除
107
+ 老人控除対象 ? 480_000 : 380_000
108
+ when 580_001 .. 950_000
109
+ 380_000
110
+ when 950_001 .. 1_000_000
111
+ 360_000
112
+ when 1_000_001 .. 1_050_000
113
+ 310_000
114
+ when 1_050_001 .. 1_100_000
115
+ 260_000
116
+ when 1_100_001 .. 1_150_000
117
+ 210_000
118
+ when 1_150_001 .. 1_200_000
119
+ 160_000
120
+ when 1_200_001 .. 1_250_000
121
+ 110_000
122
+ when 1_250_001 .. 1_300_000
123
+ 60_000
124
+ else
125
+ 30_000
126
+ end
127
+ elsif 所得金額 <= 9_500_000
128
+ case 配偶者の所得金額
129
+ when 0 .. 580_000
130
+ 老人控除対象 ? 320_000 : 260_000
131
+ when 580_001 .. 950_000
132
+ 260_000
133
+ when 950_001 .. 1_000_000
134
+ 240_000
135
+ when 1_000_001 .. 1_050_000
136
+ 210_000
137
+ when 1_050_001 .. 1_100_000
138
+ 180_000
139
+ when 1_100_001 .. 1_150_000
140
+ 140_000
141
+ when 1_150_001 .. 1_200_000
142
+ 110_000
143
+ when 1_200_001 .. 1_250_000
144
+ 80_000
145
+ when 1_250_001 .. 1_300_000
146
+ 40_000
147
+ else
148
+ 20_000
149
+ end
150
+ else
151
+ case 配偶者の所得金額
152
+ when 0 .. 580_000
153
+ 老人控除対象 ? 160_000 : 130_000
154
+ when 580_001 .. 950_000
155
+ 130_000
156
+ when 950_001 .. 1_000_000
157
+ 120_000
158
+ when 1_000_001 .. 1_050_000
159
+ 110_000
160
+ when 1_050_001 .. 1_100_000
161
+ 90_000
162
+ when 1_100_001 .. 1_150_000
163
+ 70_000
164
+ when 1_150_001 .. 1_200_000
165
+ 60_000
166
+ when 1_200_001 .. 1_250_000
167
+ 40_000
168
+ when 1_250_001 .. 1_300_000
169
+ 20_000
170
+ else
171
+ 10_000
172
+ end
173
+ end
174
+ end
175
+
176
+ def 特定親族特別控除額(所得金額)
177
+ return 630_000 if 所得金額.nil? # 特定扶養親族
178
+
179
+ case 所得金額
180
+ when 0 .. 580_000
181
+ 630_000 # 特定扶養親族
182
+ when 580_001 .. 850_000
183
+ 630_000
184
+ when 850_001 .. 900_000
185
+ 610_000
186
+ when 900_001 .. 950_000
187
+ 510_000
188
+ when 950_001 .. 1_000_000
189
+ 410_000
190
+ when 1_000_001 .. 1_050_000
191
+ 310_000
192
+ when 1_050_001 .. 1_100_000
193
+ 210_000
194
+ when 1_100_001 .. 1_150_000
195
+ 110_000
196
+ when 1_150_001 .. 1_200_000
197
+ 60_000
198
+ when 1_200_001 .. 1_230_000
199
+ 30_000
200
+ else
201
+ 0
202
+ end
203
+ end
204
+
205
+ # 電子計算機等による年末調整
206
+ #
207
+ def 算出所得税額(課税給与所得金額)
208
+ tax = case 課税給与所得金額
209
+ when 0 .. 1_950_000
210
+ 課税給与所得金額 * 0.05
211
+ when 1_950_001 .. 3_300_000
212
+ 課税給与所得金額 * 0.1 - 97_500
213
+ when 3_300_001 .. 6_950_000
214
+ 課税給与所得金額 * 0.2 - 427_500
215
+ when 6_950_001 .. 9_000_000
216
+ 課税給与所得金額 * 0.23 - 636_000
217
+ when 9_000_001 .. 18_000_000
218
+ 課税給与所得金額 * 0.33 - 1_536_000
219
+ when 18_000_001 .. 18_050_000
220
+ 課税給与所得金額 * 0.4 - 2_796_000
221
+ else
222
+ raise '年末調整の対象となりません'
223
+ end
224
+ (tax / 1000).floor * 1000
225
+ end
226
+
227
+ # 電子計算機等による年末調整
228
+ #
229
+ def 年調年税額(年調所得税額)
230
+ (年調所得税額 * BigDecimal('1.021') / 100).floor * 100
231
+ end
232
+
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,229 @@
1
+ # coding: utf-8
2
+ require "date"
3
+ require "bigdecimal"
4
+
5
+ module JpNationalTax #:nodoc:
6
+ module IncomeTax #:nodoc:
7
+ #
8
+ # https://www.nta.go.jp/publication/pamph/gensen/nencho2025/pdf/204.pdf
9
+ #
10
+ module Nenmatsu2027
11
+
12
+ module_function
13
+
14
+ def effective_date
15
+ Date.parse("2027-12-01")
16
+ end
17
+
18
+ # 電子計算機等による年末調整
19
+ #
20
+ def 年調給与額(給与の総額)
21
+ case 給与の総額
22
+ when 1_900_000 .. 6_599_999
23
+ 階差 = 4_000
24
+ 同一階差の最小値 = 1_900_000
25
+ 給与の総額 - ((給与の総額 - 同一階差の最小値) % 階差)
26
+ else
27
+ 給与の総額
28
+ end
29
+ end
30
+
31
+ # 電子計算機等による年末調整
32
+ #
33
+ def 給与所得控除後の給与等の金額(年調給与額)
34
+ case 年調給与額
35
+ when 0 .. 650_999
36
+ 0
37
+ when 651_000 .. 1_899_999
38
+ 年調給与額 - 650_000
39
+ when 1_900_000 .. 3_599_999
40
+ (年調給与額 * BigDecimal('0.7') + 80_000).floor
41
+ when 3_600_000 .. 6_599_999
42
+ (年調給与額 * BigDecimal('0.8') - 440_000).floor
43
+ when 6_600_000 .. 8_499_999
44
+ (年調給与額 * BigDecimal('0.9') - 1_100_000).floor
45
+ when 8_500_000 .. 20_000_000
46
+ 年調給与額 - 1_950_000
47
+ else
48
+ STDERR.puts '年末調整の対象となりません'
49
+ 年調給与額 - 1_950_000
50
+ end
51
+ end
52
+
53
+ # https://www.nta.go.jp/taxes/shiraberu/taxanswer/shotoku/1199.htm
54
+ #
55
+ def 基礎控除額(所得金額)
56
+ case 所得金額
57
+ when 0 .. 1_320_000
58
+ 950_000
59
+ when 1_320_001 .. 23_500_000
60
+ 580_000
61
+ when 23_500_001 .. 24_000_000
62
+ 480_000
63
+ when 24_000_001 .. 24_500_000
64
+ 320_000
65
+ when 24_500_001 .. 25_000_000
66
+ 160_000
67
+ else
68
+ 0
69
+ end
70
+ end
71
+
72
+ def 扶養控除の額(生年月日, 申告年, 所得金額 = 0, 同居: nil)
73
+ return 0 if 生年月日.nil?
74
+
75
+ 基準日 = Date.new(申告年, 12, 31)
76
+ if 生年月日 > 基準日.prev_year(16)
77
+ 0
78
+ elsif 生年月日 <= 基準日.prev_year(70)
79
+ return 0 if 所得金額 > 580_000
80
+ 同居 ? 580_000 : 480_000 # 老人扶養親族
81
+ elsif 生年月日 <= 基準日.prev_year(19) and 生年月日 > 基準日.prev_year(23)
82
+ 特定親族特別控除額(所得金額)
83
+ else
84
+ 所得金額 > 580_000 ? 0 : 380_000
85
+ end
86
+ end
87
+
88
+ def 配偶者特別控除の金額(所得金額, 配偶者の所得金額, 配偶者の生年月日: nil, 申告年: nil)
89
+ return 0 if 所得金額 > 10_000_000
90
+ return 0 if 配偶者の所得金額 > 1_330_000
91
+
92
+ 老人控除対象 = if 申告年 and 配偶者の生年月日
93
+ 基準日 = Date.new(申告年, 12, 31)
94
+ 配偶者の生年月日 <= 基準日.prev_year(70)
95
+ else
96
+ false
97
+ end
98
+ if 所得金額 <= 9_000_000
99
+ case 配偶者の所得金額
100
+ when 0 .. 580_000 # 配偶者控除
101
+ 老人控除対象 ? 480_000 : 380_000
102
+ when 580_001 .. 950_000
103
+ 380_000
104
+ when 950_001 .. 1_000_000
105
+ 360_000
106
+ when 1_000_001 .. 1_050_000
107
+ 310_000
108
+ when 1_050_001 .. 1_100_000
109
+ 260_000
110
+ when 1_100_001 .. 1_150_000
111
+ 210_000
112
+ when 1_150_001 .. 1_200_000
113
+ 160_000
114
+ when 1_200_001 .. 1_250_000
115
+ 110_000
116
+ when 1_250_001 .. 1_300_000
117
+ 60_000
118
+ else
119
+ 30_000
120
+ end
121
+ elsif 所得金額 <= 9_500_000
122
+ case 配偶者の所得金額
123
+ when 0 .. 580_000
124
+ 老人控除対象 ? 320_000 : 260_000
125
+ when 580_001 .. 950_000
126
+ 260_000
127
+ when 950_001 .. 1_000_000
128
+ 240_000
129
+ when 1_000_001 .. 1_050_000
130
+ 210_000
131
+ when 1_050_001 .. 1_100_000
132
+ 180_000
133
+ when 1_100_001 .. 1_150_000
134
+ 140_000
135
+ when 1_150_001 .. 1_200_000
136
+ 110_000
137
+ when 1_200_001 .. 1_250_000
138
+ 80_000
139
+ when 1_250_001 .. 1_300_000
140
+ 40_000
141
+ else
142
+ 20_000
143
+ end
144
+ else
145
+ case 配偶者の所得金額
146
+ when 0 .. 580_000
147
+ 老人控除対象 ? 160_000 : 130_000
148
+ when 580_001 .. 950_000
149
+ 130_000
150
+ when 950_001 .. 1_000_000
151
+ 120_000
152
+ when 1_000_001 .. 1_050_000
153
+ 110_000
154
+ when 1_050_001 .. 1_100_000
155
+ 90_000
156
+ when 1_100_001 .. 1_150_000
157
+ 70_000
158
+ when 1_150_001 .. 1_200_000
159
+ 60_000
160
+ when 1_200_001 .. 1_250_000
161
+ 40_000
162
+ when 1_250_001 .. 1_300_000
163
+ 20_000
164
+ else
165
+ 10_000
166
+ end
167
+ end
168
+ end
169
+
170
+ def 特定親族特別控除額(所得金額)
171
+ return 630_000 if 所得金額.nil? # 特定扶養親族
172
+
173
+ case 所得金額
174
+ when 0 .. 580_000
175
+ 630_000 # 特定扶養親族
176
+ when 580_001 .. 850_000
177
+ 630_000
178
+ when 850_001 .. 900_000
179
+ 610_000
180
+ when 900_001 .. 950_000
181
+ 510_000
182
+ when 950_001 .. 1_000_000
183
+ 410_000
184
+ when 1_000_001 .. 1_050_000
185
+ 310_000
186
+ when 1_050_001 .. 1_100_000
187
+ 210_000
188
+ when 1_100_001 .. 1_150_000
189
+ 110_000
190
+ when 1_150_001 .. 1_200_000
191
+ 60_000
192
+ when 1_200_001 .. 1_230_000
193
+ 30_000
194
+ else
195
+ 0
196
+ end
197
+ end
198
+
199
+ # 電子計算機等による年末調整
200
+ #
201
+ def 算出所得税額(課税給与所得金額)
202
+ tax = case 課税給与所得金額
203
+ when 0 .. 1_950_000
204
+ 課税給与所得金額 * 0.05
205
+ when 1_950_001 .. 3_300_000
206
+ 課税給与所得金額 * 0.1 - 97_500
207
+ when 3_300_001 .. 6_950_000
208
+ 課税給与所得金額 * 0.2 - 427_500
209
+ when 6_950_001 .. 9_000_000
210
+ 課税給与所得金額 * 0.23 - 636_000
211
+ when 9_000_001 .. 18_000_000
212
+ 課税給与所得金額 * 0.33 - 1_536_000
213
+ when 18_000_001 .. 18_050_000
214
+ 課税給与所得金額 * 0.4 - 2_796_000
215
+ else
216
+ raise '年末調整の対象となりません'
217
+ end
218
+ (tax / 1000).floor * 1000
219
+ end
220
+
221
+ # 電子計算機等による年末調整
222
+ #
223
+ def 年調年税額(年調所得税額)
224
+ (年調所得税額 * BigDecimal('1.021') / 100).floor * 100
225
+ end
226
+
227
+ end
228
+ end
229
+ end
@@ -5,8 +5,8 @@ Dir[File.expand_path("income_tax/income*.rb", __dir__)].each { |f| require_relat
5
5
 
6
6
  module JpNationalTax
7
7
  module IncomeTax
8
- MOD_M = [Kouran2020]
9
- MOD_Y = [Nenmatsu2020]
8
+ MOD_M = [Kouran2026, Kouran2020]
9
+ MOD_Y = [Nenmatsu2027, Nenmatsu2025, Nenmatsu2020]
10
10
 
11
11
  module_function
12
12
 
@@ -1,3 +1,3 @@
1
1
  module JpNationalTax
2
- VERSION = "0.1.4"
2
+ VERSION = "0.3.0"
3
3
  end
data/tools/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # eTax仕様比較ツール
2
+
3
+ [e-Tax仕様書](https://www.e-tax.nta.go.jp/shiyo/index.htm#anc05)の申告技術仕様のxlsxをもとに、バージョン間の異同を分析するツール。
4
+
5
+
6
+ ## 手続きバージョンごとの帳票バージョンリスト
7
+
8
+ 各手続きバージョンに対応する帳票バージョンのセットを特定する用途。
9
+
10
+ 1. `analyze-templates-by-proc.rb`を用いてレポートファイルを生成
11
+ * 手続きIDを指定
12
+ * `07手続一覧等/02手続内帳票対応表/`の分析対象xlsxファイルを指定。ワイルドカード利用可能
13
+
14
+
15
+ ## 帳票バージョンとフィールドの対応リスト
16
+
17
+ 各帳票フィールドの追加・削除を特定する用途。
18
+ フィールドの追加・削除は把握できるが、定義の異同はチェックしていない。
19
+
20
+ 1. `parse-etax-spec.rb`を用いてxlsxをtsvに変換
21
+ * `10XML構造設計書等【法人税】/`の分析対象xlsxファイルを指定。ワイルドカード利用可能
22
+ 2. `stats-etax-spec.rb`を用いてレポートファイルを生成
23
+ * 帳票IDを指定
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ require "csv"
3
+ require "roo"
4
+
5
+ #
6
+ # eTax仕様の手続内帳票対応表をTSV変換するツール
7
+ #
8
+ def print_usage
9
+ # ARGV[1..]にはExcelファイルのpathを指定
10
+ STDERR.puts "Usage: ruby analyze-templates-by-proc.rb <手続code> <手続内帳票対応表.xlsx files>"
11
+ end
12
+
13
+ def search_proc(sheet, proc_id)
14
+ {}.tap do |templates|
15
+ sheet.each do |row|
16
+ next if row[0] != proc_id
17
+
18
+ if templates[row[2]]
19
+ templates[row[2]][:template_ver].push(row[9])
20
+ else
21
+ template = { :name => row[1], :proc_ver => row[8], :template_ver => Array(row[9]) }
22
+ templates[row[2]] = template
23
+ end
24
+ end
25
+ if templates.empty?
26
+ STDERR.puts " #{proc_id} not found"
27
+ return nil
28
+ end
29
+ end
30
+ end
31
+
32
+ if ARGV.length < 2
33
+ print_usage
34
+ exit 1
35
+ end
36
+
37
+ proc_id = ARGV[0]
38
+ filename = "#{proc_id}.tsv"
39
+ [].tap do |procs|
40
+ ARGV[1..-1].each do |path|
41
+ xlsx = Roo::Excelx.new(path, expand_merged_ranges: true)
42
+ STDERR.puts "Processing... #{path}"
43
+ xlsx.each_with_pagename do |name, sheet|
44
+ procedure = search_proc(sheet, proc_id)
45
+ procs.push(procedure) if procedure
46
+ end
47
+ end
48
+
49
+ keys = procs.map {|procedure| procedure.keys }.flatten.uniq.sort
50
+
51
+ CSV.open(filename, "w", col_sep: "\t", force_quotes: true, quote_char: '"') do |csv|
52
+ csv << ["帳票ID", "帳票名"].concat(procs.map {|procedure| procedure.first&.last&.fetch(:proc_ver)})
53
+ keys.each do |k|
54
+ name = procs.map {|procedure| procedure.dig(k, :name) }.compact.first
55
+ csv << [k, name].concat(procs.map {|procedure| procedure[k]&.fetch(:template_ver)&.join('|')})
56
+ end
57
+ end
58
+ end
59
+
60
+ STDERR.puts "\n#{filename} saved"
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+ require "csv"
3
+ require "roo"
4
+
5
+ #
6
+ # eTax仕様のXML構造設計書をTSV変換するツール
7
+ #
8
+
9
+ TARGET_COLUMNS = {
10
+ origin: ["タグ名", "レベル", "共通ボキャブラリまたはデータ型", "項番", "備考"],
11
+ dest: ["version", "tag", "level", "struct", "order", "note", "label"],
12
+ }
13
+
14
+ def print_usage
15
+ STDERR.puts "Usage: ruby parse-etax-spec.rb <XML構造設計書.xlsx files>"
16
+ end
17
+
18
+ def search_columns(xlsx)
19
+ [].tap do |columns|
20
+ xlsx.each_row_streaming do |row|
21
+ next if row[0].value != "項番"
22
+
23
+ TARGET_COLUMNS[:origin].each do |label|
24
+ columns.push row.find_index { |cell| cell.value == label }
25
+ end
26
+ break
27
+ end
28
+ end
29
+ end
30
+
31
+ def collect_rows(xlsx, columns)
32
+ [].tap do |res|
33
+ xlsx.each_row_streaming do |row|
34
+ next unless row[0].value.to_s =~ /^[0-9]+$/
35
+
36
+ label = extract_label(row, columns[1], columns[2])
37
+ res.push(columns.map{ |col| row[col].value }.push(label))
38
+ end
39
+ end
40
+ end
41
+
42
+ def extract_label(row, prev, subs)
43
+ (prev+1...subs).map { |idx| row[idx].value }.join("")
44
+ end
45
+
46
+ def sheet_defs(xlsx)
47
+ columns = []
48
+ xlsx.each_row_streaming do |row|
49
+ next if row[0].value != "帳票名称"
50
+
51
+ ["様式ID", "帳票名称", "バージョン"].each do |label|
52
+ columns.push row.find_index { |cell| cell.value == label }
53
+ end
54
+ break
55
+ end
56
+
57
+ [].tap { |res|
58
+ xlsx.each_row_streaming do |row|
59
+ next if row[0].value == "帳票名称"
60
+
61
+ res.push columns.map { |i| row[i].value }
62
+ break
63
+ end
64
+ }.flatten
65
+ end
66
+
67
+
68
+ # ARGVにはExcelファイルのpathを指定
69
+ if ARGV.length < 1
70
+ print_usage
71
+ exit 1
72
+ end
73
+
74
+ ARGV.each do |path|
75
+ xlsx = Roo::Excelx.new(path)
76
+ STDERR.puts "Processing... #{path}"
77
+
78
+ xlsx.each_with_pagename do |name, sheet|
79
+ id, name, version = sheet_defs(xlsx)
80
+ filename = "#{id}-#{version}-#{name.gsub(/\//, '=')[0, 80]}.tsv"
81
+ columns = search_columns(sheet)
82
+
83
+ CSV.open(filename, "w", col_sep: "\t") do |csv|
84
+ csv << TARGET_COLUMNS[:dest]
85
+ collect_rows(xlsx, columns).each do |row|
86
+ csv << row.unshift(version)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ require "csv"
3
+
4
+ def print_usage
5
+ STDERR.puts "eTax仕様を変換したTSVを集計して、タグの有効バージョンをリストするツール\n"
6
+ STDERR.puts "Usage: ruby stats-etax-spec.rb <帳票コード>"
7
+ end
8
+
9
+ def accumulate_versions(attr, csv)
10
+ csv.each do |row|
11
+ attr[row['tag']] ||= { versions: [] }
12
+ attr[row['tag']][:versions].push(row['version'])
13
+ attr[row['tag']][:label] = row['label']
14
+ attr[row['tag']][:level] = row['level']
15
+ attr[row['tag']][:order] = row['order']
16
+ attr[row['tag']][:struct] = row['struct']
17
+ attr[row['tag']][:note] = row['note']
18
+ end
19
+ end
20
+
21
+ # ARGV[0]には帳票コード(ファイル名の一部)を指定
22
+ if ARGV.length < 1
23
+ print_usage
24
+ exit 1
25
+ end
26
+
27
+ attr = {}
28
+ Dir.glob("#{ARGV[0]}*.tsv").each do |path|
29
+ CSV.open(path, "r", col_sep: "\t", headers: true) do |csv|
30
+ STDERR.puts "Processing... #{path}"
31
+ accumulate_versions(attr, csv)
32
+ end
33
+ end
34
+ output = "stats-#{ARGV[0]}.tsv"
35
+ CSV.open(output, "w", col_sep: "\t") do |csv|
36
+ csv << ["tag", "count", "level", "versions", "order", "label", "struct", "note"]
37
+ attr.each do |k, v|
38
+ csv << [k, v[:versions].length, v[:level], v[:versions].join(', '), v[:order], v[:label], v[:struct], v[:note]]
39
+ end
40
+ end
41
+
42
+ STDERR.puts "\n#{output} saved"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jp-national-tax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuma Takahiro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-06 00:00:00.000000000 Z
11
+ date: 2026-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -73,8 +73,15 @@ files:
73
73
  - lib/jp_national_tax.rb
74
74
  - lib/jp_national_tax/income_tax.rb
75
75
  - lib/jp_national_tax/income_tax/income_kouran_2020.rb
76
+ - lib/jp_national_tax/income_tax/income_kouran_2026.rb
76
77
  - lib/jp_national_tax/income_tax/income_nenmatsu_2020.rb
78
+ - lib/jp_national_tax/income_tax/income_nenmatsu_2025.rb
79
+ - lib/jp_national_tax/income_tax/income_nenmatsu_2027.rb
77
80
  - lib/jp_national_tax/version.rb
81
+ - tools/README.md
82
+ - tools/analyze-templates-by-proc.rb
83
+ - tools/parse-etax-spec.rb
84
+ - tools/stats-etax-spec.rb
78
85
  homepage: https://github.com/chumaltd/jp-national-tax
79
86
  licenses: []
80
87
  metadata:
@@ -96,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
103
  - !ruby/object:Gem::Version
97
104
  version: '0'
98
105
  requirements: []
99
- rubygems_version: 3.4.10
106
+ rubygems_version: 3.4.20
100
107
  signing_key:
101
108
  specification_version: 4
102
109
  summary: Tax calculation libs for Japan National tax