lucasalary 0.1.24 → 0.1.27

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: 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