lucasalary 0.1.13 → 0.1.18
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/CHANGELOG.md +8 -0
- data/README.md +3 -0
- data/exe/luca-salary +77 -44
- data/lib/luca_salary.rb +1 -0
- data/lib/luca_salary/base.rb +22 -22
- data/lib/luca_salary/monthly.rb +24 -4
- data/lib/luca_salary/payment.rb +18 -20
- data/lib/luca_salary/version.rb +1 -1
- metadata +29 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37e8c1758e8ea780f6f124747241c5c43b4047f96e6a72ebe28d3ae546034843
|
4
|
+
data.tar.gz: b9d761bbedb5f77d222ac7e2d16cd5258ee60d52d7e2cc75ac941f1faae2b5f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de2e967a7585233f87b4f3eeac7729b9d183563fc71610f355ca4329e2ff521d23473514d62e514da8e3735fe7bde4d8bc7f5dd58afd3e3bad2add31bb98630d
|
7
|
+
data.tar.gz: b7fa56bbc2a8e15e20b6db16a7e1e4c4f6f555f0f19da175fe41e67785af84a809e7f3ee16ba1c7d5394e86038e18f0ac756f68ea26140169a1b9bb9bb8eb9dc
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
data/exe/luca-salary
CHANGED
@@ -5,60 +5,93 @@ require 'optparse'
|
|
5
5
|
require 'luca_salary'
|
6
6
|
require 'luca_salary/monthly'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
LucaSalary::Monthly.new.export_json
|
8
|
+
module LucaCmd
|
9
|
+
class Profile
|
10
|
+
def self.create(args = nil, _params = nil)
|
11
|
+
LucaSalary::Profile.gen_profile!(args.first)
|
12
|
+
end
|
14
13
|
end
|
15
|
-
end
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
15
|
+
class Payment
|
16
|
+
def self.create(args = nil, _params = nil)
|
17
|
+
if args
|
18
|
+
args << 28 if args.length == 2 # specify safe last day
|
19
|
+
LucaSalary::Monthly.new(args.join('-')).calc
|
20
|
+
else
|
21
|
+
LucaSalary::Monthly.new.calc
|
22
|
+
end
|
23
|
+
end
|
25
24
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
25
|
+
def self.export(args = nil, _params = nil)
|
26
|
+
if args
|
27
|
+
args << 28 if args.length == 2 # specify safe last day
|
28
|
+
LucaSalary::Payment.new(args.join('-')).export_json
|
29
|
+
else
|
30
|
+
LucaSalary::Payment.new.export_json
|
31
|
+
end
|
32
|
+
end
|
34
33
|
|
35
|
-
def
|
36
|
-
|
34
|
+
def self.list(args = nil, params = nil)
|
35
|
+
if args
|
36
|
+
args << 28 if args.length == 2 # specify safe last day
|
37
|
+
LucaSalary::Monthly.new(args.join('-')).report(params.dig('mode'))
|
38
|
+
else
|
39
|
+
LucaSalary::Monthly.new.report(params.dig('mode'))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
37
43
|
end
|
38
44
|
|
45
|
+
LucaRecord::Base.valid_project?
|
39
46
|
cmd = ARGV.shift
|
47
|
+
params = {}
|
40
48
|
|
41
49
|
case cmd
|
42
|
-
when
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
when /profiles?/
|
51
|
+
subcmd = ARGV.shift
|
52
|
+
case subcmd
|
53
|
+
when 'create'
|
54
|
+
OptionParser.new do |opt|
|
55
|
+
opt.banner = 'Usage: luca-salary profiles create Name'
|
56
|
+
args = opt.parse(ARGV)
|
57
|
+
LucaCmd::Profile.create(args)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
puts 'Proper subcommand needed.'
|
61
|
+
puts
|
62
|
+
puts 'Usage: luca-salary profile[s] create Name'
|
63
|
+
exit 1
|
53
64
|
end
|
54
|
-
when '
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
when 'export'
|
66
|
+
LucaCmd::Payment.export(ARGV)
|
67
|
+
when /payments?/
|
68
|
+
subcmd = ARGV.shift
|
69
|
+
case subcmd
|
70
|
+
when 'create'
|
71
|
+
OptionParser.new do |opt|
|
72
|
+
opt.banner = 'Usage: luca-salary payments create year month [date]'
|
73
|
+
args = opt.parse(ARGV)
|
74
|
+
LucaCmd::Payment.create(args)
|
75
|
+
end
|
76
|
+
when 'list'
|
77
|
+
OptionParser.new do |opt|
|
78
|
+
opt.banner = 'Usage: luca-salary payments list [--mail] year month [date]'
|
79
|
+
opt.on('--mail', 'send to managers') { |_v| params['mode'] = 'mail' }
|
80
|
+
args = opt.parse(ARGV)
|
81
|
+
LucaCmd::Payment.list(args, params)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
puts 'Proper subcommand needed.'
|
85
|
+
puts
|
86
|
+
puts 'Usage: luca-salary payment[s] (create|list) [--help|options]'
|
87
|
+
exit 1
|
61
88
|
end
|
62
89
|
else
|
63
|
-
puts '
|
90
|
+
puts 'Proper subcommand needed.'
|
91
|
+
puts
|
92
|
+
puts 'Usage: luca-salary subcommand [options]'
|
93
|
+
puts ' profiles'
|
94
|
+
puts ' payments'
|
95
|
+
puts ' export: puts payment data for LucaBook import'
|
96
|
+
exit 1
|
64
97
|
end
|
data/lib/luca_salary.rb
CHANGED
data/lib/luca_salary/base.rb
CHANGED
@@ -9,39 +9,25 @@ require 'luca_record'
|
|
9
9
|
|
10
10
|
module LucaSalary
|
11
11
|
class Base < LucaRecord::Base
|
12
|
-
attr_reader :
|
12
|
+
attr_reader :dict, :config, :pjdir
|
13
13
|
@dirname = 'payments'
|
14
14
|
|
15
15
|
def initialize(date = nil)
|
16
16
|
@date = date.nil? ? Date.today : Date.parse(date)
|
17
17
|
@pjdir = Pathname(LucaSupport::Config::Pjdir)
|
18
|
-
@config = load_config(@pjdir
|
19
|
-
@driver = set_driver
|
18
|
+
@config = load_config(@pjdir / 'config.yml')
|
20
19
|
@dict = load_dict
|
21
20
|
end
|
22
21
|
|
23
|
-
#
|
24
|
-
# call country specific calculation
|
25
|
-
#
|
26
|
-
def calc
|
27
|
-
self.class.prepare_dir!(datadir / 'payments', @date)
|
28
|
-
country = @driver.new(@pjdir, @config, @date)
|
29
|
-
LucaSalary::Profile.all do |profile|
|
30
|
-
current_profile = parse_current(profile)
|
31
|
-
h = country.calc_payment(current_profile)
|
32
|
-
LucaSalary::Payment.new(@date.to_s).create(current_profile, h)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
22
|
def gen_aggregation!
|
37
23
|
LucaSalary::Profile.all do |profile|
|
38
24
|
id = profile.dig('id')
|
39
25
|
payment = {}
|
40
26
|
targetdir = @date.year.to_s + 'Z'
|
41
|
-
past_data = LucaRecord::Base.find(id, "payments/#{targetdir}")
|
27
|
+
past_data = LucaRecord::Base.find(id, "payments/#{targetdir}")
|
42
28
|
(1..12).map do |month|
|
43
29
|
origin_dir = @date.year.to_s + [nil, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'][month]
|
44
|
-
origin = LucaRecord::Base.find(id, "payments/#{origin_dir}")
|
30
|
+
origin = LucaRecord::Base.find(id, "payments/#{origin_dir}")
|
45
31
|
# TODO: to be updated null check
|
46
32
|
if origin == {}
|
47
33
|
month
|
@@ -60,17 +46,31 @@ module LucaSalary
|
|
60
46
|
dat.filter { |k, _v| /^#{code}[0-9A-Fa-f]{,3}$/.match(k.to_s) }
|
61
47
|
end
|
62
48
|
|
49
|
+
# Subtotal each items.
|
50
|
+
# 1::
|
51
|
+
# Base salary or wages.
|
52
|
+
# 2::
|
53
|
+
# Deduction directly related to work payment, including tax, insurance, pension and so on.
|
54
|
+
# 3::
|
55
|
+
# Deduction for miscellaneous reasons.
|
56
|
+
# 4::
|
57
|
+
# Addition for miscellaneous reasons.
|
58
|
+
# 5::
|
59
|
+
# Net payment amount.
|
60
|
+
#
|
63
61
|
def amount_by_code(obj)
|
64
62
|
{}.tap do |h|
|
65
63
|
(1..4).each do |n|
|
66
|
-
|
64
|
+
code = n.to_s
|
65
|
+
h[code] = sum_code(obj, code)
|
67
66
|
end
|
67
|
+
h['5'] = h['1'] - h['2'] - h['3'] + h['4']
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
71
|
def sum_code(obj, code, exclude = nil)
|
72
|
-
target = obj.select { |k,
|
73
|
-
target = target.reject { |k,
|
72
|
+
target = obj.select { |k, _v| /^#{code}[0-9A-Fa-f]{,3}$/.match(k) }
|
73
|
+
target = target.reject { |k, _v| exclude.include?(k) } if exclude
|
74
74
|
target.values.inject(:+) || 0
|
75
75
|
end
|
76
76
|
|
@@ -88,7 +88,7 @@ module LucaSalary
|
|
88
88
|
code = @config['countryCode']
|
89
89
|
if code
|
90
90
|
require "luca_salary/#{code.downcase}"
|
91
|
-
Kernel.const_get "LucaSalary
|
91
|
+
Kernel.const_get "LucaSalary::#{code.upcase}"
|
92
92
|
else
|
93
93
|
nil
|
94
94
|
end
|
data/lib/luca_salary/monthly.rb
CHANGED
@@ -9,26 +9,46 @@ require 'luca_salary'
|
|
9
9
|
require 'luca_record'
|
10
10
|
|
11
11
|
module LucaSalary
|
12
|
-
class Monthly <
|
12
|
+
class Monthly < LucaSalary::Base
|
13
|
+
@dirname = 'payments'
|
14
|
+
|
13
15
|
def initialize(date = nil)
|
14
|
-
@date =
|
16
|
+
@date = date.nil? ? Date.today : Date.parse(date)
|
15
17
|
@pjdir = Pathname(LucaSupport::Config::Pjdir)
|
16
18
|
@config = load_config(@pjdir + 'config.yml')
|
19
|
+
@driver = set_driver
|
17
20
|
end
|
18
21
|
|
22
|
+
# call country specific calculation
|
19
23
|
#
|
24
|
+
def calc
|
25
|
+
country = @driver.new(@pjdir, @config, @date)
|
26
|
+
# TODO: handle retirement
|
27
|
+
LucaSalary::Profile.all do |profile|
|
28
|
+
current_profile = parse_current(profile)
|
29
|
+
if self.class.search(@date.year, @date.month, @date.day, current_profile['id']).count > 0
|
30
|
+
puts "payment record already exists: #{current_profile['id']}"
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
h = country.calc_payment(current_profile)
|
34
|
+
h['profile_id'] = current_profile['id']
|
35
|
+
self.class.create(h, date: @date, codes: Array(current_profile['id']))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
20
39
|
# output payslips via mail or console
|
21
40
|
#
|
22
41
|
def report(mode = nil)
|
42
|
+
data = LucaSalary::Payment.new(@date.to_s).payslip
|
23
43
|
if mode == 'mail'
|
24
44
|
mail = Mail.new do
|
25
45
|
subject '[luca salary] Monthly Payment'
|
26
46
|
end
|
27
47
|
mail.to = @config.dig('mail', 'report_mail')
|
28
|
-
mail.text_part = YAML.dump(
|
48
|
+
mail.text_part = YAML.dump(LucaSupport::Code.readable(data))
|
29
49
|
LucaSupport::Mail.new(mail, @pjdir).deliver
|
30
50
|
else
|
31
|
-
puts YAML.dump(
|
51
|
+
puts YAML.dump(LucaSupport::Code.readable(data))
|
32
52
|
end
|
33
53
|
end
|
34
54
|
|
data/lib/luca_salary/payment.rb
CHANGED
@@ -17,34 +17,28 @@ module LucaSalary
|
|
17
17
|
@dict = LucaRecord::Dict.load_tsv_dict(@pjdir / 'dict' / 'code.tsv')
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
21
|
-
# create record with LucaSalary::Profile instance and apyment data
|
22
|
-
#
|
23
|
-
def create(profile, payment)
|
24
|
-
id = profile.dig('id')
|
25
|
-
if self.class.search(@date.year, @date.month, @date.day, id).first
|
26
|
-
puts "payment record already exists: #{id}"
|
27
|
-
return nil
|
28
|
-
end
|
29
|
-
|
30
|
-
self.class.gen_record_file!('payments', @date, Array(id)) do |f|
|
31
|
-
f.write(YAML.dump(payment.sort.to_h))
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
20
|
def payslip
|
36
21
|
{}.tap do |report|
|
37
22
|
report['asof'] = "#{@date.year}/#{@date.month}"
|
23
|
+
report['payments'] = []
|
38
24
|
report['records'] = []
|
39
25
|
|
40
26
|
self.class.asof(@date.year, @date.month) do |payment|
|
27
|
+
profile = LucaSalary::Profile.find(payment['profile_id'])
|
28
|
+
summary = {
|
29
|
+
'name' => profile['name'],
|
30
|
+
"#{@dict.dig('5', :label) || '5'}" => payment['5']
|
31
|
+
}
|
32
|
+
|
41
33
|
slip = {}.tap do |line|
|
34
|
+
line['name'] = profile['name']
|
42
35
|
payment.each do |k, v|
|
43
36
|
next if k == 'id'
|
44
37
|
|
45
38
|
line["#{@dict.dig(k, :label) || k}"] = v
|
46
39
|
end
|
47
40
|
end
|
41
|
+
report['payments'] << summary
|
48
42
|
report['records'] << slip
|
49
43
|
end
|
50
44
|
end
|
@@ -61,11 +55,15 @@ module LucaSalary
|
|
61
55
|
acct_label = @dict[k][:acct_label]
|
62
56
|
h[pos][acct_label] = h[pos].key?(acct_label) ? h[pos][acct_label] + v : v
|
63
57
|
end
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
[].tap do |res|
|
59
|
+
item = {}
|
60
|
+
item['date'] = "#{@date.year}-#{@date.month}-#{@date.day}"
|
61
|
+
item['debit'] = h[:debit].map { |k, v| { 'label' => k, 'value' => v } }
|
62
|
+
item['credit'] = h[:credit].map { |k, v| { 'label' => k, 'value' => v } }
|
63
|
+
item['x-editor'] = 'LucaSalary'
|
64
|
+
res << item
|
65
|
+
puts JSON.dump(LucaSupport::Code.readable(res))
|
66
|
+
end
|
69
67
|
end
|
70
68
|
|
71
69
|
private
|
data/lib/luca_salary/version.rb
CHANGED
metadata
CHANGED
@@ -1,57 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lucasalary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lucarecord
|
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'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- - "
|
31
|
+
- - ">="
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '1.17'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- - "
|
38
|
+
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '1.17'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
42
|
+
name: minitest
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
47
|
+
version: '5.0'
|
34
48
|
type: :development
|
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: '5.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
56
|
+
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - "
|
59
|
+
- - ">="
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
61
|
+
version: 12.3.3
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - "
|
66
|
+
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
68
|
+
version: 12.3.3
|
55
69
|
description: 'Salary calculation framework
|
56
70
|
|
57
71
|
'
|
@@ -73,7 +87,8 @@ files:
|
|
73
87
|
- lib/luca_salary/profile.rb
|
74
88
|
- lib/luca_salary/version.rb
|
75
89
|
homepage: https://github.com/chumaltd/luca/tree/master/lucasalary
|
76
|
-
licenses:
|
90
|
+
licenses:
|
91
|
+
- GPL
|
77
92
|
metadata:
|
78
93
|
homepage_uri: https://github.com/chumaltd/luca/tree/master/lucasalary
|
79
94
|
source_code_uri: https://github.com/chumaltd/luca/tree/master/lucasalary
|
@@ -86,7 +101,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
101
|
requirements:
|
87
102
|
- - ">="
|
88
103
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
104
|
+
version: 2.6.0
|
90
105
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
106
|
requirements:
|
92
107
|
- - ">="
|