lucabook 0.2.26 → 0.2.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: 933e3d04315c04b7f6e998b16499b458ceeeafe8bfae9ce4ef4422018eb17040
4
- data.tar.gz: 2e243b4e85cdc50bd45e39ed311cf78a8aa12e1956be0d0273c2a634147be16c
3
+ metadata.gz: ad4b1eba3419508d64bfeade5f776ed2ca0f32313deab25660864aff47767787
4
+ data.tar.gz: 57aef956cbc763dbf4d089d5745c9cc4d6a6ed44dd3ff726b9c80fbc6b29629d
5
5
  SHA512:
6
- metadata.gz: b2292a4972ce1fcf883a828d17479f1580e3145e0db2d26ff6044a73495d2e151d60f0bd98fd5b2f945c3b74cdff879f9f7779073487c05c70a078306b069bbe
7
- data.tar.gz: 27bf6b4bcea1b2eb9d5dac761d5465ce478af02a4074f0a20038b7f8a21c528b66faf399d4364702ebf22f06cc0a0112d13a4ee2e10acb22eb16b52859aaf4b6
6
+ metadata.gz: 317b373f1a31c85c107dfa294ec6df0dcc89f13b8ab10277bb004b3bdceaaf0ec58cfa5c2220a088932965b5b156fd71fef1ce67be67c330857bbcea127de365
7
+ data.tar.gz: e7456d393a4309bafb9a3622c28da10067e1483c80b0bbbd73a05508bb3d9a6742051e2d190870a1f6e39df5ec10b5dd7d1de698faef969a3bc54efa7b46b153
data/exe/luca-book CHANGED
@@ -24,7 +24,7 @@ class LucaCmd
24
24
  if params['headers']
25
25
  render(LucaBook::ListByHeader.term(*args, code: params['code'], header: params['headers']).list_by_code, params)
26
26
  else
27
- render(LucaBook::List.term(*args, code: params['code']).list_by_code, params)
27
+ render(LucaBook::List.term(*args, code: params['code'], recursive: params[:recursive]).list_by_code(params[:recursive]), params)
28
28
  end
29
29
  else
30
30
  render(LucaBook::List.term(*args).list_journals, params)
@@ -34,7 +34,7 @@ class LucaCmd
34
34
  def self.stats(args, params)
35
35
  args = gen_range(params[:n]) if args.empty?
36
36
  if params['code']
37
- render(LucaBook::State.by_code(params['code'], *args), params)
37
+ render(LucaBook::State.by_code(params['code'], *args, recursive: params[:recursive]), params)
38
38
  else
39
39
  render(LucaBook::State.range(*args).stats(params[:level]), params)
40
40
  end
@@ -124,9 +124,11 @@ when /journals?/, 'j'
124
124
  LucaCmd::Journal.import(args, params)
125
125
  end
126
126
  when 'list'
127
+ params[:recursive] = false
127
128
  OptionParser.new do |opt|
128
129
  opt.banner = 'Usage: luca-book journals list [options] [YYYY M]'
129
130
  opt.on('-c', '--code VAL', 'filter with code or label') { |v| params['code'] = v }
131
+ opt.on('-r', '--recursive', 'include subaccounts') { |_v| params[:recursive] = true }
130
132
  opt.on('--customer', 'categorize by x-customer header') { |_v| params['headers'] = 'x-customer' }
131
133
  opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
132
134
  opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
@@ -146,9 +148,11 @@ when /journals?/, 'j'
146
148
  LucaCmd::Journal.add_header(args, params)
147
149
  end
148
150
  when 'stats'
151
+ params[:recursive] = false
149
152
  OptionParser.new do |opt|
150
153
  opt.banner = 'Usage: luca-book journals stats [options] [YYYY M]'
151
154
  opt.on('-c', '--code VAL', 'filter with code or label') { |v| params['code'] = v }
155
+ opt.on('-r', '--recursive', 'include subaccounts') { |_v| params[:recursive] = true }
152
156
  opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
153
157
  opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
154
158
  opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
@@ -74,7 +74,7 @@ module LucaBook
74
74
 
75
75
  # for assert purpose
76
76
  #
77
- def gross(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil, rows: 4)
77
+ def gross(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil, rows: 4, recursive: false)
78
78
  if ! date_range.nil?
79
79
  raise if date_range.class != Range
80
80
  # TODO: date based range search
@@ -92,14 +92,14 @@ module LucaBook
92
92
  case i
93
93
  when 0
94
94
  idx_memo = row.map(&:to_s)
95
- next if code && !idx_memo.include?(code)
95
+ next if code && idx_memo.select { |idx| /^#{code}/.match(idx) }.empty?
96
96
 
97
97
  idx_memo.each do |r|
98
98
  sum[:debit][r] ||= BigDecimal('0')
99
99
  sum[:debit_count][r] ||= 0
100
100
  end
101
101
  when 1
102
- next if code && !idx_memo.include?(code)
102
+ next if code && idx_memo.select { |idx| /^#{code}/.match(idx) }.empty?
103
103
 
104
104
  row.each_with_index do |r, j|
105
105
  sum[:debit][idx_memo[j]] += BigDecimal(r.to_s)
@@ -107,7 +107,7 @@ module LucaBook
107
107
  end
108
108
  when 2
109
109
  idx_memo = row.map(&:to_s)
110
- break if code && !idx_memo.include?(code)
110
+ break if code && idx_memo.select { |idx| /^#{code}/.match(idx) }.empty?
111
111
 
112
112
  idx_memo.each do |r|
113
113
  sum[:credit][r] ||= BigDecimal('0')
@@ -123,13 +123,21 @@ module LucaBook
123
123
  end
124
124
  end
125
125
  end
126
- if code
127
- sum[:debit] = sum[:debit][code] || BigDecimal('0')
128
- sum[:credit] = sum[:credit][code] || BigDecimal('0')
129
- sum[:debit_count] = sum[:debit_count][code] || 0
130
- sum[:credit_count] = sum[:credit_count][code] || 0
126
+ return sum if code.nil?
127
+
128
+ codes = if recursive
129
+ sum[:debit].keys.concat(sum[:credit].keys).uniq.select { |k| /^#{code}/.match(k) }
130
+ else
131
+ Array(code)
132
+ end
133
+ res = { debit: 0, credit: 0, debit_count: 0, credit_count: 0 }
134
+ codes.each do |code|
135
+ res[:debit] += sum[:debit][code] || BigDecimal('0')
136
+ res[:credit] += sum[:credit][code] || BigDecimal('0')
137
+ res[:debit_count] += sum[:debit_count][code] || 0
138
+ res[:credit_count] += sum[:credit_count][code] || 0
131
139
  end
132
- sum
140
+ res
133
141
  end
134
142
 
135
143
  # netting vouchers in specified term
@@ -21,13 +21,17 @@ module LucaBook #:nodoc:
21
21
  @start = start_date
22
22
  end
23
23
 
24
- def self.term(from_year, from_month, to_year = from_year, to_month = from_month, code: nil, basedir: @dirname)
24
+ def self.term(from_year, from_month, to_year = from_year, to_month = from_month, code: nil, basedir: @dirname, recursive: false)
25
25
  code = search_code(code) if code
26
26
  data = LucaBook::Journal.term(from_year, from_month, to_year, to_month, code).select do |dat|
27
27
  if code.nil?
28
28
  true
29
29
  else
30
- [:debit, :credit].map { |key| serialize_on_key(dat[key], :code) }.flatten.include?(code)
30
+ if recursive
31
+ ! [:debit, :credit].map { |key| serialize_on_key(dat[key], :code) }.flatten.select { |idx| /^#{code}/.match(idx) }.empty?
32
+ else
33
+ [:debit, :credit].map { |key| serialize_on_key(dat[key], :code) }.flatten.include?(code)
34
+ end
31
35
  end
32
36
  end
33
37
  new data, Date.new(from_year.to_i, from_month.to_i, 1), code
@@ -43,13 +47,13 @@ module LucaBook #:nodoc:
43
47
  end
44
48
  end
45
49
 
46
- def list_by_code
47
- calc_code
50
+ def list_by_code(recursive = false)
51
+ calc_code(recursive: recursive)
48
52
  convert_label
49
53
  @data = [code_header] + @data.map do |dat|
50
54
  date, txid = LucaSupport::Code.decode_id(dat[:id])
51
55
  {}.tap do |res|
52
- res['code'] = dat[:code]
56
+ res['code'] = dat[:code].length == 1 ? dat[:code].first : dat[:code]
53
57
  res['date'] = date
54
58
  res['no'] = txid
55
59
  res['id'] = dat[:id]
@@ -99,30 +103,22 @@ module LucaBook #:nodoc:
99
103
 
100
104
  private
101
105
 
102
- def set_balance
106
+ def set_balance(recursive = false)
103
107
  return BigDecimal('0') if @code.nil? || /^[A-H]/.match(@code)
104
108
 
105
- balance_dict = Dict.latest_balance(@start)
106
- start_balance = BigDecimal(balance_dict.dig(@code.to_s, :balance) || '0')
107
- start = Dict.issue_date(balance_dict)&.next_month
108
- last = @start.prev_month
109
- if last.year >= start.year && last.month >= start.month
110
- start_balance + self.class.term(start.year, start.month, last.year, last.month, code: @code).accumulate_code
111
- else
112
- start_balance
113
- end
109
+ LucaBook::State.start_balance(@start.year, @start.month, recursive: recursive)
114
110
  end
115
111
 
116
- def calc_code
117
- @balance = set_balance
112
+ def calc_code(recursive: false)
113
+ @balance = set_balance(recursive)[@code] || BigDecimal('0')
118
114
  if @code
119
115
  balance = @balance
120
116
  @data.each do |dat|
121
117
  dat[:diff] = Util.diff_by_code(dat[:debit], @code) - Util.diff_by_code(dat[:credit], @code)
122
118
  balance += dat[:diff]
123
119
  dat[:balance] = balance
124
- dat[:code] = @code
125
- counter = dat[:diff] * Util.pn_debit(@code) > 0 ? :credit : :debit
120
+ target, counter = dat[:diff] * Util.pn_debit(@code) > 0 ? [:debit, :credit] : [:credit, :debit]
121
+ dat[:code] = dat[target].map { |d| d[:code] }
126
122
  dat[:counter_code] = dat[counter].map { |d| d[:code] }
127
123
  end
128
124
  end
@@ -132,7 +128,7 @@ module LucaBook #:nodoc:
132
128
  def convert_label
133
129
  @data.each do |dat|
134
130
  if @code
135
- dat[:code] = "#{dat[:code]} #{@@dict.dig(dat[:code], :label)}"
131
+ dat[:code] = dat[:code].map { |target| "#{target} #{@@dict.dig(target, :label)}" }
136
132
  dat[:counter_code] = dat[:counter_code].map { |counter| "#{counter} #{@@dict.dig(counter, :label)}" }
137
133
  else
138
134
  dat[:debit].each { |debit| debit[:code] = "#{debit[:code]} #{@@dict.dig(debit[:code], :label)}" }
@@ -27,7 +27,7 @@ module LucaBook
27
27
  @count = count
28
28
  @start_date = start_d
29
29
  @end_date = end_d
30
- @start_balance = set_balance
30
+ set_balance
31
31
  end
32
32
 
33
33
  def self.range(from_year, from_month, to_year = from_year, to_month = from_month)
@@ -50,25 +50,29 @@ module LucaBook
50
50
  )
51
51
  end
52
52
 
53
- def self.by_code(code, from_year, from_month, to_year = from_year, to_month = from_month)
53
+ def self.by_code(code, from_year, from_month, to_year = from_year, to_month = from_month, recursive: false)
54
54
  code = search_code(code) if code
55
55
  date = Date.new(from_year.to_i, from_month.to_i, -1)
56
56
  last_date = Date.new(to_year.to_i, to_month.to_i, -1)
57
57
  raise 'invalid term specified' if date > last_date
58
58
 
59
- reports = [].tap do |r|
59
+ balance = start_balance(date.year, date.month, recursive: recursive)[code] || 0
60
+ first_line = { 'code' => nil, 'label' => nil, 'debit_amount' => nil, 'debit_count' => nil, 'credit_amount' => nil, 'credit_count' => nil, 'net' => nil, 'balance' => balance, '_d' => nil }
61
+ reports = [first_line].tap do |r|
60
62
  while date <= last_date do
61
63
  diff = {}.tap do |h|
62
- g = gross(date.year, date.month, code: code)
64
+ g = gross(date.year, date.month, code: code, recursive: recursive)
63
65
  sum = g.dig(:debit).nil? ? BigDecimal('0') : Util.calc_diff(g[:debit], code)
64
66
  sum -= g.dig(:credit).nil? ? BigDecimal('0') : Util.calc_diff(g[:credit], code)
67
+ balance += sum
65
68
  h['code'] = code
66
- h['label'] = LucaRecord::Dict.load('base.tsv').dig(code, :label)
67
- h['net'] = sum
69
+ h['label'] = @@dict.dig(code, :label)
68
70
  h['debit_amount'] = g[:debit]
69
71
  h['debit_count'] = g[:debit_count]
70
72
  h['credit_amount'] = g[:credit]
71
73
  h['credit_count'] = g[:credit_count]
74
+ h['net'] = sum
75
+ h['balance'] = balance
72
76
  h['_d'] = date.to_s
73
77
  end
74
78
  r << diff
@@ -205,25 +209,28 @@ module LucaBook
205
209
  end
206
210
 
207
211
  def set_balance
208
- pre_last = @start_date.prev_month
209
- start_year = if @start_date.month > CONFIG['fy_start'].to_i
210
- pre_last.year
211
- else
212
- pre_last.year - 1
213
- end
214
- pre = self.class.accumulate_term(start_year, CONFIG['fy_start'], pre_last.year, pre_last.month)
215
-
216
- base = Dict.latest_balance(@start_date).each_with_object({}) do |(k, v), h|
212
+ @start_balance = self.class.start_balance(@start_date.year, @start_date.month)
213
+ end
214
+
215
+ def self.start_balance(year, month, recursive: true)
216
+ start_date = Date.new(year, month, 1)
217
+ base = Dict.latest_balance(start_date).each_with_object({}) do |(k, v), h|
217
218
  h[k] = BigDecimal(v[:balance].to_s) if v[:balance]
218
219
  h[k] ||= BigDecimal('0') if k.length == 2
219
220
  end
220
- if pre
221
- idx = (pre.keys + base.keys).uniq
222
- base = {}.tap do |h|
223
- idx.each { |k| h[k] = (base[k] || BigDecimal('0')) + (pre[k] || BigDecimal('0')) }
221
+ if month == CONFIG['fy_start'].to_i
222
+ return recursive ? total_subaccount(base) : base
223
+ end
224
+
225
+ pre_last = start_date.prev_month
226
+ year -= 1 if month <= CONFIG['fy_start'].to_i
227
+ pre = accumulate_term(year, CONFIG['fy_start'], pre_last.year, pre_last.month)
228
+ total = {}.tap do |h|
229
+ (pre.keys + base.keys).uniq.each do |k|
230
+ h[k] = (base[k] || BigDecimal('0')) + (pre[k] || BigDecimal('0'))
224
231
  end
225
232
  end
226
- self.class.total_subaccount(base)
233
+ recursive ? total_subaccount(total) : total
227
234
  end
228
235
 
229
236
  def render_xbrl(filename = nil)
@@ -24,7 +24,7 @@ module LucaBook
24
24
 
25
25
  def amount_by_code(items, code)
26
26
  items
27
- .select { |item| item.dig(:code) == code }
27
+ .select { |item| /^#{code}/.match(item[:code]) }
28
28
  .inject(BigDecimal('0')) { |sum, item| sum + item[:amount] }
29
29
  end
30
30
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LucaBook
4
- VERSION = '0.2.26'
4
+ VERSION = '0.2.27'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lucabook
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.26
4
+ version: 0.2.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chuma Takahiro