lucasalary 0.1.24 → 0.1.27

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49f2002c8bc5ec17d605422ee282c0b7cb6053f88aa2fa3dce308e9dbbbdc5c5
4
- data.tar.gz: e993bd468b91510ad9dc68e55b58c54be562b0dcb76f9a757d4f88b6392d860d
3
+ metadata.gz: 21cf8c51a5487b6c97376fe3ce9093dca20a7dc00943101f023ddf883bb20bf3
4
+ data.tar.gz: 427756bed92e1878f48763decf1924a475e3f70163f0a68fd48efd767c224a8b
5
5
  SHA512:
6
- metadata.gz: 3847524b19036ca598ae119613fd49a9983ce54cdcd37f233b02fead3c636de0f4dfb2c5f80c459c1bc9d8eda82aa8ac22ddc12326fbbcb3cc13e21f9b159804
7
- data.tar.gz: 15758df4fb112cf71614d11315a6477ebc5506a9176c4c29867dfc7776ea549d7a15ffe38ca1b3edab2c7993c09ae3d89ef82ef0fea01fde89538854ae4a984c
6
+ metadata.gz: 12943976db746cb20edb83d007efdd94a4ed69f11f05dd5fc3970e778955c199a1c713223e16106df5e58deea659e91630525144d40215f9aa731750147bd4c5
7
+ data.tar.gz: de251e1584866528cecde0dc2c76fd5da91c344622cb63f3d281fb9516a75958d2d5d1ab2ee7770c97452572c6847c1064cc5febc0be7f81f7dc55691fac72b8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## LucaSalary 0.1.27
2
+
3
+ * Implement LucaSalary::Total for Year totaling.
4
+
5
+ ## LucaSalary 0.1.26
6
+
7
+ * Add `luca-salary payments report`: monthly statement by code.
8
+
9
+ ## LucaSalary 0.1.25
10
+
11
+ * Add `luca-salary payments total --adjust`: applying yearly tax refund.
12
+
1
13
  ## LucaSalary 0.1.24
2
14
 
3
15
  * Fix: remove null record from `luca-salary export` JSON
data/exe/luca-salary CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'json'
4
5
  require 'optparse'
5
6
  require 'luca_salary'
6
7
  require 'luca_salary/monthly'
@@ -40,8 +41,27 @@ module LucaCmd
40
41
  end
41
42
  end
42
43
 
43
- def self.total(args = nil, _params = nil)
44
- LucaSalary::Payment.year_total(args.first.to_i)
44
+ def self.report(args = nil, params = nil)
45
+ render(LucaSalary::State.range(*args).report(), params)
46
+ end
47
+
48
+ def self.total(args = nil, params = nil)
49
+ if params['mode'] == 'adjust'
50
+ LucaSalary::Payment.year_adjust(args[0].to_i, args[1].to_i)
51
+ else
52
+ LucaSalary::Payment.year_total(args.first.to_i)
53
+ end
54
+ end
55
+
56
+ def self.render(dat, params)
57
+ case params[:output]
58
+ when 'json'
59
+ puts JSON.dump(dat)
60
+ when 'nu'
61
+ LucaSupport::View.nushell(YAML.dump(dat))
62
+ else
63
+ puts YAML.dump(dat)
64
+ end
45
65
  end
46
66
  end
47
67
  end
@@ -84,11 +104,19 @@ when /payments?/
84
104
  args = opt.parse(ARGV)
85
105
  LucaCmd::Payment.list(args, params)
86
106
  end
107
+ when 'report'
108
+ OptionParser.new do |opt|
109
+ opt.banner = 'Usage: luca-salary payments report [--nu] year month [year month]'
110
+ opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
111
+ args = opt.parse(ARGV)
112
+ LucaCmd::Payment.report(args, params)
113
+ end
87
114
  when 'total'
88
115
  OptionParser.new do |opt|
89
- opt.banner = 'Usage: luca-salary payments total year'
116
+ opt.banner = 'Usage: luca-salary payments total [--adjust] year [month]'
117
+ opt.on('--adjust', 'Apply year total adjustment to payslip of year/month') { |_v| params['mode'] = 'adjust' }
90
118
  args = opt.parse(ARGV)
91
- LucaCmd::Payment.total(args)
119
+ LucaCmd::Payment.total(args, params)
92
120
  end
93
121
  else
94
122
  puts 'Proper subcommand needed.'
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LucaSalary
4
+ module Accumulator
5
+ def self.included(klass) #:nodoc:
6
+ klass.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def accumulate(records)
11
+ count = 0
12
+ result = records.each_with_object({}) do |record, result|
13
+ count += 1
14
+ record
15
+ .select { |k, _v| /^[1-4][0-9A-Fa-f]{,3}$/.match(k) }
16
+ .each do |k, v|
17
+ next if v.nil?
18
+
19
+ result[k] = result[k] ? result[k] + v : v
20
+ end
21
+ end
22
+ [result, count]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -45,7 +45,9 @@ module LucaSalary
45
45
 
46
46
  def self.sum_code(obj, code, exclude = nil)
47
47
  target = obj.select { |k, _v| /^#{code}[0-9A-Fa-f]{,3}$/.match(k) }
48
- target = target.reject { |k, _v| exclude.include?(k) } if exclude
48
+ target = target
49
+ .reject { |_k, v| v.nil? }
50
+ .reject { |k, _v| exclude&.include?(k) }
49
51
  target.values.inject(:+) || 0
50
52
  end
51
53
 
@@ -9,6 +9,8 @@ require 'luca_record'
9
9
 
10
10
  module LucaSalary
11
11
  class Payment < LucaRecord::Base
12
+ include Accumulator
13
+
12
14
  @dirname = 'payments'
13
15
 
14
16
  def initialize(date = nil)
@@ -47,21 +49,9 @@ module LucaSalary
47
49
  def self.year_total(year)
48
50
  Profile.all do |profile|
49
51
  id = profile.dig('id')
50
- payment = { 'profile_id' => id }
51
- # payment = {}
52
- (1..12).each do |month|
53
- search(year, month, nil, id).each do |origin|
54
- # TODO: to be updated null check
55
- if origin == {}
56
- month
57
- else
58
- origin.select { |k, _v| /^[1-4][0-9A-Fa-f]{,3}$/.match(k) }.each do |k, v|
59
- payment[k] = payment[k] ? payment[k] + v : v
60
- end
61
- nil
62
- end
63
- end
64
- end
52
+ slips = term(year, 1, year, 12, id)
53
+ payment, _count = accumulate(slips)
54
+ payment['profile_id'] = id
65
55
  date = Date.new(year, 12, 31)
66
56
  payment = local_convert(payment, date)
67
57
  create(payment, date: date, codes: [id], basedir: 'payments/total')
@@ -78,6 +68,31 @@ module LucaSalary
78
68
  return payment
79
69
  end
80
70
 
71
+ # Apply adjustment for yearly refund.
72
+ # Search Year Total records 6 months before specified payslip month.
73
+ #
74
+ def self.year_adjust(year, month)
75
+ target_month = Date.new(year, month, 1)
76
+ total_st = target_month.prev_month(6)
77
+ search(year, month).each do |slip, path|
78
+ term(total_st.year, total_st.month, year, month, slip['profile_id'], "#{@dirname}/total/") do |total|
79
+ slip['3A1'] = total['3A1']
80
+ slip['4A1'] = total['4A1']
81
+ end
82
+ # Recalculate sum
83
+ ['3', '4'].each do |key|
84
+ slip[key] = 0
85
+ slip[key] = LucaSalary::Base.sum_code(slip, key)
86
+ slip['5'] = slip['1'] - slip['2'] - slip['3'] + slip['4']
87
+ end
88
+ update_record(
89
+ @dirname,
90
+ path,
91
+ YAML.dump(LucaSupport::Code.readable(slip.sort.to_h))
92
+ )
93
+ end
94
+ end
95
+
81
96
  # Export json for LucaBook.
82
97
  # Accrual_date can be change with `payment_term` on config.yml. Default value is 0.
83
98
  # `payment_term: 1` means payment on the next month of calculation target.
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'luca_support'
4
+ require 'luca_record'
5
+
6
+ module LucaSalary
7
+ class State < LucaRecord::Base
8
+ include Accumulator
9
+
10
+ @dirname = 'payments'
11
+
12
+ def initialize(data, count = nil, start_d: nil, end_d: nil)
13
+ @monthly = data
14
+ @count = count
15
+ @start_date = start_d
16
+ @end_date = end_d
17
+ @dict = LucaRecord::Dict.load_tsv_dict(Pathname(LucaSupport::PJDIR) / 'dict' / 'code.tsv')
18
+ end
19
+
20
+ def self.range(from_year, from_month, to_year = from_year, to_month = from_month)
21
+ date = Date.new(from_year.to_i, from_month.to_i, -1)
22
+ last_date = Date.new(to_year.to_i, to_month.to_i, -1)
23
+ raise 'invalid term specified' if date > last_date
24
+
25
+ counts = []
26
+ reports = [].tap do |r|
27
+ while date <= last_date do
28
+ slips = term(date.year, date.month, date.year, date.month)
29
+ record, count = accumulate(slips)
30
+ r << record.tap { |c| c['_d'] = date.to_s }
31
+ counts << count
32
+ date = Date.new(date.next_month.year, date.next_month.month, -1)
33
+ end
34
+ end
35
+ new(reports, counts,
36
+ start_d: Date.new(from_year.to_i, from_month.to_i, 1),
37
+ end_d: Date.new(to_year.to_i, to_month.to_i, -1)
38
+ )
39
+ end
40
+
41
+ def report()
42
+ total, _count = LucaSalary::State.accumulate(@monthly)
43
+ total['_d'] = 'total'
44
+ [@monthly, total].flatten.map do |m|
45
+ {}.tap do |r|
46
+ m.sort.to_h.each do |k, v|
47
+ r["#{@dict.dig(k, :label) || k}"] = readable(v)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'luca_support'
4
+ require 'luca_record'
5
+
6
+ module LucaSalary
7
+ class Total < LucaRecord::Base
8
+ @dirname = 'payments/total'
9
+
10
+ attr_reader :slips
11
+
12
+ def initialize(year)
13
+ @date = Date.new(year.to_i, 12, -1)
14
+ @slips = Total.term(year, 1, year, 12).map do |slip, _path|
15
+ slip['profile'] = parse_current(Profile.find_secure(slip['profile_id']))
16
+ slip
17
+ end
18
+ @dict = LucaRecord::Dict.load_tsv_dict(Pathname(LucaSupport::PJDIR) / 'dict' / 'code.tsv')
19
+ end
20
+ end
21
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LucaSalary
4
- VERSION = '0.1.24'
4
+ VERSION = '0.1.27'
5
5
  end
data/lib/luca_salary.rb CHANGED
@@ -4,7 +4,10 @@ require 'luca_record'
4
4
  require 'luca_salary/version'
5
5
 
6
6
  module LucaSalary
7
+ autoload :Accumulator, 'luca_salary/accumulator'
7
8
  autoload :Base, 'luca_salary/base'
8
9
  autoload :Payment, 'luca_salary/payment'
9
10
  autoload :Profile, 'luca_salary/profile'
11
+ autoload :State, 'luca_salary/state'
12
+ autoload :Total, 'luca_salary/total'
10
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lucasalary
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.24
4
+ version: 0.1.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuma Takahiro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-19 00:00:00.000000000 Z
11
+ date: 2023-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lucarecord
@@ -81,10 +81,13 @@ files:
81
81
  - README.md
82
82
  - exe/luca-salary
83
83
  - lib/luca_salary.rb
84
+ - lib/luca_salary/accumulator.rb
84
85
  - lib/luca_salary/base.rb
85
86
  - lib/luca_salary/monthly.rb
86
87
  - lib/luca_salary/payment.rb
87
88
  - lib/luca_salary/profile.rb
89
+ - lib/luca_salary/state.rb
90
+ - lib/luca_salary/total.rb
88
91
  - lib/luca_salary/version.rb
89
92
  homepage: https://github.com/chumaltd/luca/tree/master/lucasalary
90
93
  licenses:
@@ -108,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
111
  - !ruby/object:Gem::Version
109
112
  version: '0'
110
113
  requirements: []
111
- rubygems_version: 3.3.5
114
+ rubygems_version: 3.4.1
112
115
  signing_key:
113
116
  specification_version: 4
114
117
  summary: Salary calculation framework