luca-jp 0.20.4 → 0.20.6
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 +17 -0
- data/lib/luca/jp/util.rb +4 -0
- data/lib/luca/jp/version.rb +1 -1
- data/lib/luca_salary/jp/version.rb +1 -1
- data/lib/luca_salary/jp_adjustment.rb +271 -0
- data/lib/luca_salary/jp_payreport.rb +10 -6
- metadata +31 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dfd6af4ff40f3d2562f04f71b59e02c944fec0fbc66dc18ae72d868bda2c5b82
|
|
4
|
+
data.tar.gz: 42f779967ee6e22db9a488bebdfa1c123e8c1738532f78e3ed5201916d92ca8a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b7f6ceb960f5dee8eea66435f631567123e7d98757fbb07f607b20fea1725516a87f054f1f48e7173b7fe4d343c644d51f0b5b11904ee681db7cde43e80a9be
|
|
7
|
+
data.tar.gz: 1e4929bef66fc8459ce622c75c590e49d1fdc5a96ac7d4d3e63543ba1971490f69bfd1fc62c469da03111a4973561579a11a76683f055c0b1ef749ce3e4fc9f8
|
data/exe/luca-jp
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
require 'optparse'
|
|
5
5
|
require 'luca/jp'
|
|
6
6
|
require 'luca_cmd'
|
|
7
|
+
require 'luca_salary/jp_adjustment'
|
|
7
8
|
require 'luca_salary/jp_payreport'
|
|
8
9
|
require 'luca_support/const'
|
|
9
10
|
require 'yaml'
|
|
@@ -76,6 +77,13 @@ module LucaSalaryCmd
|
|
|
76
77
|
puts LucaSalary::JpPayreport.export(args.first)
|
|
77
78
|
end
|
|
78
79
|
end
|
|
80
|
+
|
|
81
|
+
class Import
|
|
82
|
+
def self.profiles(args, params = nil)
|
|
83
|
+
path, id = args
|
|
84
|
+
puts LucaSalary::JpAdjustment.import(path, id, params)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
79
87
|
end
|
|
80
88
|
|
|
81
89
|
#LucaRecord::Base.valid_project?
|
|
@@ -135,6 +143,14 @@ when 'k', 'kyuyo', 'salary'
|
|
|
135
143
|
LucaSalaryCmd::Export.payreport(args)
|
|
136
144
|
end
|
|
137
145
|
end
|
|
146
|
+
when 'n', /nenmats?u/, /nenmats?u-?chou?sei/
|
|
147
|
+
OptionParser.new do |opt|
|
|
148
|
+
opt.banner = 'Usage: luca-jp nenmatsu <zip-file-path> <profile id>'
|
|
149
|
+
args = opt.parse(ARGV)
|
|
150
|
+
LucaCmd.check_dir('profiles', ext_conf: EXT_CONF) do
|
|
151
|
+
LucaSalaryCmd::Import.profiles(args, params)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
138
154
|
when 'version'
|
|
139
155
|
puts "luca-jp: version #{Luca::Jp::VERSION}"
|
|
140
156
|
exit 0
|
|
@@ -146,6 +162,7 @@ else
|
|
|
146
162
|
puts ' s[youhizei]: 消費税の計算'
|
|
147
163
|
puts ' c[hihouzei]: 地方税の計算'
|
|
148
164
|
puts ' k[yuyo]: 給与報告(所得税)の計算'
|
|
165
|
+
puts ' n[enmatsu]: 年末調整アプリのデータインポート'
|
|
149
166
|
puts ' urikake: 勘定科目内訳明細書の売掛金リスト(CSV)'
|
|
150
167
|
exit 1
|
|
151
168
|
end
|
data/lib/luca/jp/util.rb
CHANGED
data/lib/luca/jp/version.rb
CHANGED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'luca_salary'
|
|
3
|
+
require 'luca_support/const'
|
|
4
|
+
require 'luca/jp/util'
|
|
5
|
+
require 'zip'
|
|
6
|
+
|
|
7
|
+
require 'rexml/document'
|
|
8
|
+
|
|
9
|
+
module LucaSalary
|
|
10
|
+
class JpAdjustment < LucaSalary::Profile
|
|
11
|
+
|
|
12
|
+
def self.import(path, id = nil, params = nil)
|
|
13
|
+
s_profile = profiles(id)
|
|
14
|
+
bulk_load(path).each do |o|
|
|
15
|
+
s_profile['spouse']['name'] ||= o['spouse']['name']
|
|
16
|
+
s_profile['spouse']['katakana'] ||= o['spouse']['kana']
|
|
17
|
+
s_profile['spouse']['income'].merge!(o['spouse']['income'])
|
|
18
|
+
if ! s_profile['family'].empty? || ! o['family'].empty?
|
|
19
|
+
s_profile['family'] = merge_family(s_profile['family'].concat(o['family']))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
save(s_profile, 's_profiles')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.profiles(id = nil)
|
|
26
|
+
if id
|
|
27
|
+
list = id_completion(id, basedir: 's_profiles')
|
|
28
|
+
id = if list.length > 1
|
|
29
|
+
raise "#{list.length} entries found for ID: #{id}. abort..."
|
|
30
|
+
else
|
|
31
|
+
list.first
|
|
32
|
+
end
|
|
33
|
+
#merged = find_secure(id, 'profiles') # NOTE for content match by name, birth_date
|
|
34
|
+
find(id, 's_profiles')
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# XMLタグ定義: https://www.nta.go.jp/users/gensen/oshirase/0019004-159.htm
|
|
39
|
+
#
|
|
40
|
+
TAGS = {
|
|
41
|
+
'NTAAPP001' => {
|
|
42
|
+
year: 'xml001_B00020',
|
|
43
|
+
family: {
|
|
44
|
+
root: 'xml001_D00000', # 扶養親族情報繰り返し
|
|
45
|
+
kana: 'xml001_D00020', # フリガナ
|
|
46
|
+
name: 'xml001_D00030', # 氏名
|
|
47
|
+
birth_date: {
|
|
48
|
+
root: 'xml001_D00080', # 生年月日
|
|
49
|
+
year: 'xml001_D00090', # 西暦
|
|
50
|
+
month: 'xml001_D00120', # 月
|
|
51
|
+
day: 'xml001_D00130' # 日
|
|
52
|
+
},
|
|
53
|
+
income: 'xml001_D00160', # 本年中の所得の見積額
|
|
54
|
+
elderly: 'xml001_D00140', # 老人扶養親族
|
|
55
|
+
tokutei: 'xml001_D00150', # 特定扶養親族/特定親族
|
|
56
|
+
nonresident: 'xml001_D00170', # 非居住者である親族/控除対象外国外扶養親族
|
|
57
|
+
handicapped: {
|
|
58
|
+
root: 'xml001_D00290', # 障害者である事実
|
|
59
|
+
type: 'xml001_D00300' # 障害者区分
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
'NTAAPP004' => {
|
|
64
|
+
year: 'xml004_B00020',
|
|
65
|
+
spouse: {
|
|
66
|
+
root: 'xml004_D00000',
|
|
67
|
+
kana: 'xml004_D00010', # フリガナ
|
|
68
|
+
name: 'xml004_D00020', # 氏名
|
|
69
|
+
income: 'xml004_D00260', # 配偶者の本年中の合計所得金額の見積額
|
|
70
|
+
elderly: 'xml004_D00160', # 老人控除対象配偶者 (1: 該当)
|
|
71
|
+
nonresident: 'xml004_D00170' # 非居住者である配偶者
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
def self.parse_xml(xml_set)
|
|
77
|
+
h = { 'spouse' => { 'income' => {} }, 'family' => [] }
|
|
78
|
+
xml_set.each do |xml|
|
|
79
|
+
# ルート要素の属性から様式IDを取得
|
|
80
|
+
form_id = xml.root.name
|
|
81
|
+
tags = TAGS[form_id]
|
|
82
|
+
next unless tags
|
|
83
|
+
|
|
84
|
+
year_node = xml.elements["//#{tags[:year]}"]
|
|
85
|
+
year = year_node&.text&.to_i
|
|
86
|
+
|
|
87
|
+
# NTAAPP001: 扶養控除等申告書
|
|
88
|
+
if form_id == 'NTAAPP001'
|
|
89
|
+
xml.elements.each("//#{tags[:family][:root]}") do |dep|
|
|
90
|
+
f = {}
|
|
91
|
+
f['name'] = dep.elements[tags[:family][:name]]&.text
|
|
92
|
+
f['kana'] = dep.elements[tags[:family][:kana]]&.text
|
|
93
|
+
|
|
94
|
+
bd_tags = tags[:family][:birth_date]
|
|
95
|
+
bd_node = dep.elements[bd_tags[:root]]
|
|
96
|
+
if bd_node
|
|
97
|
+
y = bd_node.elements[bd_tags[:year]]&.text
|
|
98
|
+
m = bd_node.elements[bd_tags[:month]]&.text
|
|
99
|
+
d = bd_node.elements[bd_tags[:day]]&.text
|
|
100
|
+
if y && m && d
|
|
101
|
+
f['birth_date'] = Date.new(y.to_i, m.to_i, d.to_i)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if year
|
|
106
|
+
dep_income = dep.elements[tags[:family][:income]]&.text
|
|
107
|
+
if dep_income && !dep_income.empty?
|
|
108
|
+
f['income'] = { year => dep_income.to_i }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
elderly = dep.elements[tags[:family][:elderly]]&.text
|
|
112
|
+
if elderly && (elderly == '1' || elderly == '2')
|
|
113
|
+
f['elderly'] = { year => elderly.to_i }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
tokutei = dep.elements[tags[:family][:tokutei]]&.text
|
|
117
|
+
if tokutei && (tokutei == '1' || tokutei == '2')
|
|
118
|
+
f['tokutei'] = { year => tokutei.to_i }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
nonresident = dep.elements[tags[:family][:nonresident]]&.text
|
|
122
|
+
f['nonresident'] = { year => nonresident.to_i } if nonresident == '1'
|
|
123
|
+
|
|
124
|
+
hc_tags = tags[:family][:handicapped]
|
|
125
|
+
hc_node = dep.elements[hc_tags[:root]]
|
|
126
|
+
if hc_node
|
|
127
|
+
hc_type = hc_node.elements[hc_tags[:type]]&.text
|
|
128
|
+
if hc_type && !hc_type.empty? && hc_type != '0'
|
|
129
|
+
f['handicapped'] = { year => hc_type.to_i }
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
h['family'] << f
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# NTAAPP004: 配偶者控除等申告書
|
|
139
|
+
if form_id == 'NTAAPP004'
|
|
140
|
+
if year
|
|
141
|
+
spouse = xml.elements["//#{tags[:spouse][:root]}"]
|
|
142
|
+
if spouse
|
|
143
|
+
h['spouse']['name'] = spouse.elements[tags[:spouse][:name]]&.text
|
|
144
|
+
h['spouse']['kana'] = spouse.elements[tags[:spouse][:kana]]&.text
|
|
145
|
+
|
|
146
|
+
nonresident = spouse.elements[tags[:spouse][:nonresident]]&.text
|
|
147
|
+
if nonresident == '1'
|
|
148
|
+
h['spouse']['nonresident'] = {} unless h['spouse']['nonresident']
|
|
149
|
+
h['spouse']['nonresident'][year] = nonresident.to_i
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
income = spouse.elements[tags[:spouse][:income]]&.text
|
|
153
|
+
h['spouse']['income'][year] = income.to_i if income && !income.empty?
|
|
154
|
+
|
|
155
|
+
elderly = spouse.elements[tags[:spouse][:elderly]]&.text
|
|
156
|
+
h['spouse']['elderly'] = '1' if elderly == '1'
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
h['family'] = merge_family(h['family']) # 翌年の扶養控除等申告書との重複
|
|
163
|
+
h
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def self.merge_family(family_list)
|
|
167
|
+
merged = {}
|
|
168
|
+
family_list.each do |f|
|
|
169
|
+
key = [f['name'].gsub(" ", "").strip, f['birth_date']]
|
|
170
|
+
if merged.key?(key)
|
|
171
|
+
target = merged[key]
|
|
172
|
+
|
|
173
|
+
['income', 'elderly', 'tokutei', 'nonresident', 'handicapped'].each do |field|
|
|
174
|
+
if f[field]
|
|
175
|
+
target[field] ||= {}
|
|
176
|
+
target[field].merge!(f[field])
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
else
|
|
180
|
+
merged[key] = f
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
merged.values
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def self.bulk_load(path)
|
|
187
|
+
return enum_for(:bulk_load, path) unless block_given?
|
|
188
|
+
|
|
189
|
+
has_many = if File.directory?(path)
|
|
190
|
+
children = Dir.children(path).map { |c| File.join(path, c) }
|
|
191
|
+
has_subdir = children.any? { |c| File.directory?(c) }
|
|
192
|
+
has_zip = children.any? { |c| File.file?(c) && File.extname(c).downcase == '.zip' }
|
|
193
|
+
|
|
194
|
+
has_subdir || has_zip
|
|
195
|
+
elsif File.file?(path)
|
|
196
|
+
if File.extname(path).downcase == '.zip'
|
|
197
|
+
false
|
|
198
|
+
else
|
|
199
|
+
raise "Unsupported file type: #{path}"
|
|
200
|
+
end
|
|
201
|
+
else
|
|
202
|
+
raise "Path not found: #{path}"
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
if has_many
|
|
206
|
+
# NOTE implement search by content logic
|
|
207
|
+
raise "Multiple import is not supported yet."
|
|
208
|
+
|
|
209
|
+
Dir.children(path).sort.map do |child|
|
|
210
|
+
full_path = File.join(path, child)
|
|
211
|
+
if File.directory?(full_path) || (File.file?(full_path) && File.extname(full_path).downcase == '.zip')
|
|
212
|
+
data = load_xml_export(full_path)
|
|
213
|
+
yield parse_xml(data) unless data.empty?
|
|
214
|
+
else
|
|
215
|
+
nil
|
|
216
|
+
end
|
|
217
|
+
end.compact
|
|
218
|
+
else
|
|
219
|
+
data = load_xml_export(path)
|
|
220
|
+
yield parse_xml(data) unless data.empty?
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# 年末調整アプリのエクスポートデータ読み込み(非暗号zipまたはzipを解凍したディレクトリをサポート)
|
|
225
|
+
def self.load_xml_export(path)
|
|
226
|
+
docs = []
|
|
227
|
+
if File.directory?(path)
|
|
228
|
+
Dir.children(path).sort.each do |child|
|
|
229
|
+
full_path = File.join(path, child)
|
|
230
|
+
next if File.directory?(full_path)
|
|
231
|
+
|
|
232
|
+
ext = File.extname(child).downcase
|
|
233
|
+
if ext == '.xml'
|
|
234
|
+
begin
|
|
235
|
+
docs << REXML::Document.new(File.read(full_path))
|
|
236
|
+
rescue StandardError => e
|
|
237
|
+
STDERR.puts "#{full_path}: #{e.message}"
|
|
238
|
+
end
|
|
239
|
+
elsif ext == '.zip'
|
|
240
|
+
# skip without warning
|
|
241
|
+
else
|
|
242
|
+
STDERR.puts full_path
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
return docs
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
if File.file?(path) && File.extname(path).downcase == '.zip'
|
|
249
|
+
Zip::File.open(path) do |zip|
|
|
250
|
+
zip.each do |entry|
|
|
251
|
+
next if entry.directory?
|
|
252
|
+
|
|
253
|
+
ext = File.extname(entry.name).downcase
|
|
254
|
+
if ext == '.xml'
|
|
255
|
+
begin
|
|
256
|
+
docs << REXML::Document.new(entry.get_input_stream.read)
|
|
257
|
+
rescue StandardError => e
|
|
258
|
+
STDERR.puts "#{entry.name}: #{e.message}"
|
|
259
|
+
end
|
|
260
|
+
elsif ext == '.zip'
|
|
261
|
+
# skip without warning
|
|
262
|
+
else
|
|
263
|
+
STDERR.puts entry.name
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
docs
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'luca_salary'
|
|
3
3
|
require 'luca_support/const'
|
|
4
|
+
require 'luca/jp/util'
|
|
5
|
+
|
|
4
6
|
require 'csv'
|
|
5
7
|
require 'open3'
|
|
6
8
|
|
|
@@ -39,7 +41,7 @@ end
|
|
|
39
41
|
private
|
|
40
42
|
|
|
41
43
|
def 給与支払報告明細行(slip, company, year)
|
|
42
|
-
[
|
|
44
|
+
record = [
|
|
43
45
|
315, # 法定資料の種類
|
|
44
46
|
提出義務者(company),
|
|
45
47
|
0, # 提出区分(新規0, 追加1, 訂正2, 取消3)
|
|
@@ -49,18 +51,20 @@ def 給与支払報告明細行(slip, company, year)
|
|
|
49
51
|
支払を受ける者の詳細(slip, year),
|
|
50
52
|
company['tax_id'], # 法人番号
|
|
51
53
|
支払を受ける者の扶養情報(slip['profile'], year),
|
|
52
|
-
slip['911'] == 480_000 ? nil : slip['911'], #
|
|
54
|
+
(year <= 2024 && slip['911'] == 480_000) ? nil : slip['911'], # 基礎控除の額
|
|
53
55
|
nil, # 所得金額調整控除額 TODO: 未実装 措法41の3の3
|
|
54
56
|
nil, # ひとり親
|
|
55
|
-
|
|
56
|
-
]
|
|
57
|
+
]
|
|
58
|
+
record << [nil, nil, nil] if year >= 2025 # 特定親族控除 TODO: 未実装
|
|
59
|
+
record << 提出先判定(slip) # 必須:作成区分(国税のみ0, 地方のみ1, 両方2)
|
|
60
|
+
record.flatten
|
|
57
61
|
end
|
|
58
62
|
|
|
59
63
|
def 提出義務者(company)
|
|
60
64
|
[
|
|
61
65
|
nil, # 整理番号1
|
|
62
66
|
nil, # 本支店等区分番号
|
|
63
|
-
['address', 'address2'].map { |attr| company[attr] }
|
|
67
|
+
['address', 'address2'].map { |attr| Luca::Jp::Util.alphadigit_ja(company[attr]) }
|
|
64
68
|
.compact.join(' '), # 必須:住所又は所在地
|
|
65
69
|
company['name'], # 必須:氏名又は名称
|
|
66
70
|
company['tel'], # 電話番号
|
|
@@ -72,7 +76,7 @@ end
|
|
|
72
76
|
|
|
73
77
|
def 支払を受ける者(profile)
|
|
74
78
|
[
|
|
75
|
-
['address', 'address2'].map { |attr| profile[attr] }
|
|
79
|
+
['address', 'address2'].map { |attr| Luca::Jp::Util.alphadigit_ja(profile[attr]) }
|
|
76
80
|
.compact.join(' '), # 必須:住所又は居所
|
|
77
81
|
nil, # 国外住所表示(国内は"0"、国外は"1")
|
|
78
82
|
profile['name'], # 必須:氏名
|
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.20.
|
|
4
|
+
version: 0.20.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chuma Takahiro
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-01-
|
|
11
|
+
date: 2026-01-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lucabook
|
|
@@ -80,6 +80,34 @@ dependencies:
|
|
|
80
80
|
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: 0.3.1
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rexml
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.4'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - "~>"
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '3.4'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: rubyzip
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '3.0'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '3.0'
|
|
83
111
|
- !ruby/object:Gem::Dependency
|
|
84
112
|
name: bundler
|
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -185,6 +213,7 @@ files:
|
|
|
185
213
|
- lib/luca_salary/jp.rb
|
|
186
214
|
- lib/luca_salary/jp/insurance.rb
|
|
187
215
|
- lib/luca_salary/jp/version.rb
|
|
216
|
+
- lib/luca_salary/jp_adjustment.rb
|
|
188
217
|
- lib/luca_salary/jp_payreport.rb
|
|
189
218
|
homepage: https://github.com/chumaltd/luca-jp
|
|
190
219
|
licenses:
|