lucabook 0.2.8 → 0.2.17
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-book +90 -46
- data/lib/luca_book.rb +5 -0
- data/lib/luca_book/console.rb +7 -15
- data/lib/luca_book/dict.rb +10 -3
- data/lib/luca_book/import.rb +53 -45
- data/lib/luca_book/journal.rb +26 -22
- data/lib/luca_book/list.rb +138 -0
- data/lib/luca_book/setup.rb +39 -0
- data/lib/luca_book/state.rb +151 -98
- data/lib/luca_book/templates/base-jp.xbrl.erb +78 -0
- data/lib/luca_book/templates/dict-en.tsv +142 -0
- data/lib/luca_book/templates/dict-jp.tsv +158 -0
- data/lib/luca_book/util.rb +46 -0
- data/lib/luca_book/version.rb +1 -1
- metadata +24 -4
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require 'date'
|
5
|
+
require 'luca_support'
|
6
|
+
require 'luca_record'
|
7
|
+
require 'luca_record/dict'
|
8
|
+
require 'luca_book'
|
9
|
+
|
10
|
+
# Journal List on specified term
|
11
|
+
#
|
12
|
+
module LucaBook
|
13
|
+
class List < LucaBook::Journal
|
14
|
+
@dirname = 'journals'
|
15
|
+
|
16
|
+
def initialize(data, start_date, code = nil)
|
17
|
+
@data = data
|
18
|
+
@code = code
|
19
|
+
@start = start_date
|
20
|
+
@dict = LucaRecord::Dict.load('base.tsv')
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.term(from_year, from_month, to_year = from_year, to_month = from_month, code: nil, basedir: @dirname)
|
24
|
+
data = LucaBook::Journal.term(from_year, from_month, to_year, to_month, code).select do |dat|
|
25
|
+
if code.nil?
|
26
|
+
true
|
27
|
+
else
|
28
|
+
[:debit, :credit].map { |key| serialize_on_key(dat[key], :code) }.flatten.include?(code)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
new data, Date.new(from_year.to_i, from_month.to_i, 1), code
|
32
|
+
end
|
33
|
+
|
34
|
+
def list_on_code
|
35
|
+
calc_code
|
36
|
+
convert_label
|
37
|
+
@data = [code_header] + @data.map do |dat|
|
38
|
+
date, txid = LucaSupport::Code.decode_id(dat[:id])
|
39
|
+
{}.tap do |res|
|
40
|
+
res['code'] = dat[:code]
|
41
|
+
res['date'] = date
|
42
|
+
res['no'] = txid
|
43
|
+
res['id'] = dat[:id]
|
44
|
+
res['diff'] = dat[:diff]
|
45
|
+
res['balance'] = dat[:balance]
|
46
|
+
res['counter_code'] = dat[:counter_code].length == 1 ? dat[:counter_code].first : dat[:counter_code]
|
47
|
+
res['note'] = dat[:note]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def list_journals
|
54
|
+
convert_label
|
55
|
+
@data = @data.map do |dat|
|
56
|
+
date, txid = LucaSupport::Code.decode_id(dat[:id])
|
57
|
+
{}.tap do |res|
|
58
|
+
res['date'] = date
|
59
|
+
res['no'] = txid
|
60
|
+
res['id'] = dat[:id]
|
61
|
+
res['debit_code'] = dat[:debit].length == 1 ? dat[:debit][0][:code] : dat[:debit].map { |d| d[:code] }
|
62
|
+
res['debit_amount'] = dat[:debit].inject(0) { |sum, d| sum + d[:amount] }
|
63
|
+
res['credit_code'] = dat[:credit].length == 1 ? dat[:credit][0][:code] : dat[:credit].map { |d| d[:code] }
|
64
|
+
res['credit_amount'] = dat[:credit].inject(0) { |sum, d| sum + d[:amount] }
|
65
|
+
res['note'] = dat[:note]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def accumulate_code
|
72
|
+
@data.inject(BigDecimal('0')) do |sum, dat|
|
73
|
+
sum + Util.diff_by_code(dat[:debit], @code) - Util.diff_by_code(dat[:credit], @code)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_yaml
|
78
|
+
YAML.dump(LucaSupport::Code.readable(@data)).tap { |data| puts data }
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def set_balance
|
84
|
+
return BigDecimal('0') if @code.nil? || /^[A-H]/.match(@code)
|
85
|
+
|
86
|
+
balance_dict = Dict.latest_balance
|
87
|
+
start_balance = BigDecimal(balance_dict.dig(@code.to_s, :balance) || '0')
|
88
|
+
start = Dict.issue_date(balance_dict)&.next_month
|
89
|
+
last = @start.prev_month
|
90
|
+
if last.year >= start.year && last.month >= start.month
|
91
|
+
start_balance + self.class.term(start.year, start.month, last.year, last.month, code: @code).accumulate_code
|
92
|
+
else
|
93
|
+
start_balance
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def calc_code
|
98
|
+
@balance = set_balance
|
99
|
+
if @code
|
100
|
+
balance = @balance
|
101
|
+
@data.each do |dat|
|
102
|
+
dat[:diff] = Util.diff_by_code(dat[:debit], @code) - Util.diff_by_code(dat[:credit], @code)
|
103
|
+
balance += dat[:diff]
|
104
|
+
dat[:balance] = balance
|
105
|
+
dat[:code] = @code
|
106
|
+
counter = dat[:diff] * Util.pn_debit(@code) > 0 ? :credit : :debit
|
107
|
+
dat[:counter_code] = dat[counter].map { |d| d[:code] }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def convert_label
|
114
|
+
@data.each do |dat|
|
115
|
+
if @code
|
116
|
+
dat[:code] = "#{dat[:code]} #{@dict.dig(dat[:code], :label)}"
|
117
|
+
dat[:counter_code] = dat[:counter_code].map { |counter| "#{counter} #{@dict.dig(counter, :label)}" }
|
118
|
+
else
|
119
|
+
dat[:debit].each { |debit| debit[:code] = "#{debit[:code]} #{@dict.dig(debit[:code], :label)}" }
|
120
|
+
dat[:credit].each { |credit| credit[:code] = "#{credit[:code]} #{@dict.dig(credit[:code], :label)}" }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
self
|
124
|
+
end
|
125
|
+
|
126
|
+
def dict
|
127
|
+
LucaBook::Dict::Data
|
128
|
+
end
|
129
|
+
|
130
|
+
def code_header
|
131
|
+
{}.tap do |h|
|
132
|
+
%w[code date no id diff balance counter_code note].each do |k|
|
133
|
+
h[k] = k == 'balance' ? @balance : ''
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'luca_book'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module LucaBook
|
7
|
+
class Setup
|
8
|
+
# create project skeleton under specified directory
|
9
|
+
def self.create_project(country = nil, dir = LucaSupport::Config::Pjdir)
|
10
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
11
|
+
Dir.chdir(dir) do
|
12
|
+
%w[data/journals data/balance dict].each do |subdir|
|
13
|
+
FileUtils.mkdir_p(subdir) unless Dir.exist?(subdir)
|
14
|
+
end
|
15
|
+
dict = if File.exist?("#{__dir__}/templates/dict-#{country}.tsv")
|
16
|
+
"dict-#{country}.tsv"
|
17
|
+
else
|
18
|
+
'dict-en.tsv'
|
19
|
+
end
|
20
|
+
FileUtils.cp("#{__dir__}/templates/#{dict}", 'dict/base.tsv') unless File.exist?('dict/base.tsv')
|
21
|
+
prepare_starttsv(dict) unless File.exist? 'data/balance/start.tsv'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generate initial balance template.
|
26
|
+
# Codes are same as base dictionary.
|
27
|
+
# The previous month of start date is better for _date.
|
28
|
+
#
|
29
|
+
def self.prepare_starttsv(dict)
|
30
|
+
CSV.open('data/balance/start.tsv', 'w', col_sep: "\t", encoding: 'UTF-8') do |csv|
|
31
|
+
csv << ['code', 'label', 'balance']
|
32
|
+
csv << ['_date', '2020-1-1']
|
33
|
+
CSV.open("#{__dir__}/templates/#{dict}", 'r', col_sep: "\t", encoding: 'UTF-8').each do |row|
|
34
|
+
csv << row if /^[1-9]/.match(row[0])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/luca_book/state.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
|
2
3
|
require 'csv'
|
3
4
|
require 'pathname'
|
@@ -7,7 +8,6 @@ require 'luca_record'
|
|
7
8
|
require 'luca_record/dict'
|
8
9
|
require 'luca_book'
|
9
10
|
|
10
|
-
#
|
11
11
|
# Statement on specified term
|
12
12
|
#
|
13
13
|
module LucaBook
|
@@ -17,9 +17,11 @@ module LucaBook
|
|
17
17
|
|
18
18
|
attr_reader :statement
|
19
19
|
|
20
|
-
def initialize(data)
|
20
|
+
def initialize(data, count = nil)
|
21
21
|
@data = data
|
22
|
+
@count = count
|
22
23
|
@dict = LucaRecord::Dict.load('base.tsv')
|
24
|
+
@start_balance = set_balance
|
23
25
|
end
|
24
26
|
|
25
27
|
# TODO: not compatible with LucaRecord::Base.open_records
|
@@ -41,66 +43,42 @@ module LucaBook
|
|
41
43
|
last_date = Date.new(to_year.to_i, to_month.to_i, -1)
|
42
44
|
raise 'invalid term specified' if date > last_date
|
43
45
|
|
46
|
+
counts = []
|
44
47
|
reports = [].tap do |r|
|
45
48
|
while date <= last_date do
|
46
|
-
|
49
|
+
diff, count = accumulate_month(date.year, date.month)
|
50
|
+
r << diff
|
51
|
+
counts << count
|
47
52
|
date = date.next_month
|
48
53
|
end
|
49
54
|
end
|
50
|
-
new reports
|
55
|
+
new reports, counts
|
51
56
|
end
|
52
57
|
|
53
58
|
def by_code(code, year=nil, month=nil)
|
54
|
-
raise
|
59
|
+
raise 'not supported year range yet' if ! year.nil? && month.nil?
|
55
60
|
|
56
|
-
|
57
|
-
full_term = scan_terms
|
61
|
+
balance = @book.load_start.dig(code) || 0
|
62
|
+
full_term = self.class.scan_terms
|
58
63
|
if ! month.nil?
|
59
|
-
pre_term = full_term.select{|y,m| y <= year.to_i && m < month.to_i }
|
60
|
-
|
61
|
-
[{ code: code, balance:
|
64
|
+
pre_term = full_term.select { |y, m| y <= year.to_i && m < month.to_i }
|
65
|
+
balance += pre_term.map { |y, m| self.class.net(y, m)}.inject(0){|sum, h| sum + h[code] }
|
66
|
+
[{ code: code, balance: balance, note: "#{code} #{@dict.dig(code, :label)}" }] + records_with_balance(year, month, code, balance)
|
62
67
|
else
|
63
|
-
start = { code: code, balance:
|
64
|
-
full_term.map {|y, m| y }.uniq.map {|y|
|
65
|
-
records_with_balance(y, nil, code,
|
68
|
+
start = { code: code, balance: balance, note: "#{code} #{@dict.dig(code, :label)}" }
|
69
|
+
full_term.map { |y, m| y }.uniq.map { |y|
|
70
|
+
records_with_balance(y, nil, code, balance)
|
66
71
|
}.flatten.prepend(start)
|
67
72
|
end
|
68
73
|
end
|
69
74
|
|
70
75
|
def records_with_balance(year, month, code, balance)
|
71
76
|
@book.search(year, month, nil, code).each do |h|
|
72
|
-
balance +=
|
77
|
+
balance += Util.calc_diff(Util.amount_by_code(h[:debit], code), code) - Util.calc_diff(Util.amount_by_code(h[:credit], code), code)
|
73
78
|
h[:balance] = balance
|
74
79
|
end
|
75
80
|
end
|
76
81
|
|
77
|
-
#
|
78
|
-
# TODO: useless method. consider to remove
|
79
|
-
#
|
80
|
-
def accumulate_all
|
81
|
-
current = @book.load_start
|
82
|
-
target = []
|
83
|
-
Dir.chdir(@book.pjdir) do
|
84
|
-
net_records = scan_terms(@book.pjdir).map do |year, month|
|
85
|
-
target << [year, month]
|
86
|
-
accumulate_month(year, month)
|
87
|
-
end
|
88
|
-
all_keys = net_records.map{|h| h.keys}.flatten.uniq
|
89
|
-
net_records.each.with_index(0) do |diff, i|
|
90
|
-
all_keys.each {|key| diff[key] = 0 unless diff.has_key?(key)}
|
91
|
-
diff.each do |k,v|
|
92
|
-
if current[k]
|
93
|
-
current[k] += v
|
94
|
-
else
|
95
|
-
current[k] = v
|
96
|
-
end
|
97
|
-
end
|
98
|
-
f = { target: "#{target[i][0]}-#{target[i][1]}", diff: diff.sort, current: current.sort }
|
99
|
-
yield f
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
82
|
def to_yaml
|
105
83
|
YAML.dump(code2label).tap { |data| puts data }
|
106
84
|
end
|
@@ -114,33 +92,105 @@ module LucaBook
|
|
114
92
|
end
|
115
93
|
end
|
116
94
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
95
|
+
def stats(level = nil)
|
96
|
+
keys = @count.map(&:keys).flatten.uniq.sort
|
97
|
+
@count.map! do |data|
|
98
|
+
keys.each do |k|
|
99
|
+
data[k] ||= 0
|
100
|
+
next if level.nil? || k.length <= level
|
101
|
+
|
102
|
+
if data[k[0, level]]
|
103
|
+
data[k[0, level]] += data[k]
|
104
|
+
else
|
105
|
+
data[k[0, level]] = data[k]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
data.select! { |k, _v| k.length <= level } if level
|
109
|
+
data.sort.to_h
|
120
110
|
end
|
121
|
-
|
111
|
+
keys.map! { |k| k[0, level] }.uniq.select! { |k| k.length <= level } if level
|
112
|
+
@count.prepend({}.tap { |header| keys.each { |k| header[k] = @dict.dig(k, :label) }})
|
113
|
+
puts YAML.dump(@count)
|
114
|
+
@count
|
122
115
|
end
|
123
116
|
|
124
|
-
def
|
125
|
-
@
|
126
|
-
|
117
|
+
def bs(level = 3, legal: false)
|
118
|
+
@data.map! { |data| data.select { |k, _v| k.length <= level } }
|
119
|
+
@data.map! { |data| code_sum(data).merge(data) } if legal
|
120
|
+
base = accumulate_balance(@data)
|
121
|
+
length = [base[:debit].length, base[:credit].length].max
|
122
|
+
@statement = [].tap do |a|
|
123
|
+
length.times do |i|
|
124
|
+
{}.tap do |res|
|
125
|
+
res['debit_label'] = base[:debit][i] ? @dict.dig(base[:debit][i].keys[0], :label) : ''
|
126
|
+
res['debit_balance'] = base[:debit][i] ? @start_balance.dig(base[:debit][i].keys[0]) + base[:debit][i].values[0] : ''
|
127
|
+
res['debit_diff'] = base[:debit][i] ? base[:debit][i].values[0] : ''
|
128
|
+
res['credit_label'] = base[:credit][i] ? @dict.dig(base[:credit][i].keys[0], :label) : ''
|
129
|
+
res['credit_balance'] = base[:credit][i] ? @start_balance.dig(base[:credit][i].keys[0]) + base[:credit][i].values[0] : ''
|
130
|
+
res['credit_diff'] = base[:credit][i] ? base[:credit][i].values[0] : ''
|
131
|
+
a << res
|
132
|
+
end
|
133
|
+
end
|
127
134
|
end
|
135
|
+
puts YAML.dump(@statement)
|
128
136
|
self
|
129
137
|
end
|
130
138
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
139
|
+
def accumulate_balance(monthly_diffs)
|
140
|
+
data = monthly_diffs.each_with_object({}) do |month, h|
|
141
|
+
month.each do |k, v|
|
142
|
+
h[k] = h[k].nil? ? v : h[k] + v
|
143
|
+
end
|
144
|
+
end.sort.to_h
|
145
|
+
{ debit: [], credit: [] }.tap do |res|
|
146
|
+
data.each do |k, v|
|
147
|
+
case k
|
148
|
+
when /^[0-4].*/
|
149
|
+
res[:debit] << { k => v }
|
150
|
+
when /^[5-9H].*/
|
151
|
+
res[:credit] << { k => v }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
134
155
|
end
|
135
156
|
|
136
|
-
def
|
137
|
-
|
138
|
-
|
139
|
-
|
157
|
+
def pl
|
158
|
+
@statement = @data.map { |data| data.select { |k, _v| /^[A-H].+/.match(k) } }
|
159
|
+
@statement << @statement.each_with_object({}) { |item, h| item.each { |k, v| h[k].nil? ? h[k] = v : h[k] += v } }
|
160
|
+
self
|
140
161
|
end
|
141
162
|
|
163
|
+
def self.accumulate_month(year, month)
|
164
|
+
monthly_record, count = net(year, month)
|
165
|
+
[total_subaccount(monthly_record), count]
|
166
|
+
end
|
167
|
+
|
168
|
+
# Accumulate Level 2, 3 account.
|
169
|
+
#
|
142
170
|
def self.total_subaccount(report)
|
143
|
-
|
171
|
+
{}.tap do |res|
|
172
|
+
res['10'] = sum_matched(report, /^[123][0-9A-Z]{2,}/)
|
173
|
+
res['40'] = sum_matched(report, /^[4][0-9A-Z]{2,}/)
|
174
|
+
res['50'] = sum_matched(report, /^[56][0-9A-Z]{2,}/)
|
175
|
+
res['70'] = sum_matched(report, /^[78][0-9A-Z]{2,}/)
|
176
|
+
res['8ZZ'] = res['50'] + res['70']
|
177
|
+
res['9ZZ'] = sum_matched(report, /^[9][0-9A-Z]{2,}/)
|
178
|
+
res['A0'] = sum_matched(report, /^[A][0-9A-Z]{2,}/)
|
179
|
+
res['B0'] = sum_matched(report, /^[B][0-9A-Z]{2,}/)
|
180
|
+
res['BA'] = res['A0'] - res['B0']
|
181
|
+
res['C0'] = sum_matched(report, /^[C][0-9A-Z]{2,}/)
|
182
|
+
res['CA'] = res['BA'] - res['C0']
|
183
|
+
res['D0'] = sum_matched(report, /^[D][0-9A-Z]{2,}/)
|
184
|
+
res['E0'] = sum_matched(report, /^[E][0-9A-Z]{2,}/)
|
185
|
+
res['EA'] = res['CA'] + res['D0'] - res['E0']
|
186
|
+
res['F0'] = sum_matched(report, /^[F][0-9A-Z]{2,}/)
|
187
|
+
res['G0'] = sum_matched(report, /^[G][0-9A-Z]{2,}/)
|
188
|
+
res['GA'] = res['EA'] + res['F0'] - res['G0']
|
189
|
+
res['HA'] = res['GA'] - sum_matched(report, /^[H][0-9A-Z]{2,}/)
|
190
|
+
|
191
|
+
res['1'] = res['10'] + res['40']
|
192
|
+
res['5'] = res['8ZZ'] + res['9ZZ'] + res['HA']
|
193
|
+
|
144
194
|
report.each do |k, v|
|
145
195
|
if k.length >= 4
|
146
196
|
if res[k[0, 3]]
|
@@ -150,26 +200,23 @@ module LucaBook
|
|
150
200
|
end
|
151
201
|
end
|
152
202
|
end
|
153
|
-
res
|
154
|
-
res['40'] = sum_matched(report, /^[4].[^0]}/)
|
155
|
-
res['50'] = sum_matched(report, /^[56].[^0]/)
|
156
|
-
res['70'] = sum_matched(report, /^[78].[^0]/)
|
157
|
-
res['90'] = sum_matched(report, /^[9].[^0]/)
|
158
|
-
res['A0'] = sum_matched(report, /^[A].[^0]/)
|
159
|
-
res['B0'] = sum_matched(report, /^[B].[^0]/)
|
160
|
-
res['BA'] = res['A0'] - res['B0']
|
161
|
-
res['C0'] = sum_matched(report, /^[C].[^0]/)
|
162
|
-
res['CA'] = res['BA'] - res['C0']
|
163
|
-
res['D0'] = sum_matched(report, /^[D].[^0]/)
|
164
|
-
res['E0'] = sum_matched(report, /^[E].[^0]/)
|
165
|
-
res['EA'] = res['CA'] + res['D0'] - res['E0']
|
166
|
-
res['F0'] = sum_matched(report, /^[F].[^0]/)
|
167
|
-
res['G0'] = sum_matched(report, /^[G].[^0]/)
|
168
|
-
res['GA'] = res['EA'] + res['F0'] - res['G0']
|
169
|
-
res['HA'] = res['GA'] - sum_matched(report, /^[H].[^0]/)
|
203
|
+
res.sort.to_h
|
170
204
|
end
|
171
205
|
end
|
172
206
|
|
207
|
+
def code_sum(report)
|
208
|
+
legal_items.each.with_object({}) do |k, h|
|
209
|
+
h[k] = self.class.sum_matched(report, /^#{k}.*/)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def set_balance
|
214
|
+
base = Dict.latest_balance.each_with_object({}) do |(k, v), h|
|
215
|
+
h[k] = v[:balance].to_i if v[:balance]
|
216
|
+
end
|
217
|
+
code_sum(base).merge(self.class.total_subaccount(base))
|
218
|
+
end
|
219
|
+
|
173
220
|
def self.sum_matched(report, reg)
|
174
221
|
report.select { |k, v| reg.match(k)}.values.sum
|
175
222
|
end
|
@@ -181,7 +228,7 @@ module LucaBook
|
|
181
228
|
# TODO: date based range search
|
182
229
|
end
|
183
230
|
|
184
|
-
sum = { debit: {}, credit: {} }
|
231
|
+
sum = { debit: {}, credit: {}, debit_count: {}, credit_count: {} }
|
185
232
|
idx_memo = []
|
186
233
|
asof(year, month) do |f, _path|
|
187
234
|
CSV.new(f, headers: false, col_sep: "\t", encoding: 'UTF-8')
|
@@ -190,14 +237,26 @@ module LucaBook
|
|
190
237
|
case i
|
191
238
|
when 0
|
192
239
|
idx_memo = row.map(&:to_s)
|
193
|
-
idx_memo.each
|
240
|
+
idx_memo.each do |r|
|
241
|
+
sum[:debit][r] ||= 0
|
242
|
+
sum[:debit_count][r] ||= 0
|
243
|
+
end
|
194
244
|
when 1
|
195
|
-
row.each_with_index
|
245
|
+
row.each_with_index do |r, j|
|
246
|
+
sum[:debit][idx_memo[j]] += r.to_i # TODO: bigdecimal support
|
247
|
+
sum[:debit_count][idx_memo[j]] += 1
|
248
|
+
end
|
196
249
|
when 2
|
197
250
|
idx_memo = row.map(&:to_s)
|
198
|
-
idx_memo.each
|
251
|
+
idx_memo.each do |r|
|
252
|
+
sum[:credit][r] ||= 0
|
253
|
+
sum[:credit_count][r] ||= 0
|
254
|
+
end
|
199
255
|
when 3
|
200
|
-
row.each_with_index
|
256
|
+
row.each_with_index do |r, j|
|
257
|
+
sum[:credit][idx_memo[j]] += r.to_i # TODO: bigdecimal support
|
258
|
+
sum[:credit_count][idx_memo[j]] += 1
|
259
|
+
end
|
201
260
|
else
|
202
261
|
puts row # for debug
|
203
262
|
end
|
@@ -210,17 +269,20 @@ module LucaBook
|
|
210
269
|
def self.net(year, month = nil, code = nil, date_range = nil)
|
211
270
|
g = gross(year, month, code, date_range)
|
212
271
|
idx = (g[:debit].keys + g[:credit].keys).uniq.sort
|
213
|
-
{}
|
272
|
+
count = {}
|
273
|
+
diff = {}.tap do |sum|
|
214
274
|
idx.each do |code|
|
215
|
-
sum[code] = g.dig(:debit, code).nil? ? 0 : calc_diff(g[:debit][code], code)
|
216
|
-
sum[code] -= g.dig(:credit, code).nil? ? 0 : calc_diff(g[:credit][code], code)
|
275
|
+
sum[code] = g.dig(:debit, code).nil? ? 0 : Util.calc_diff(g[:debit][code], code)
|
276
|
+
sum[code] -= g.dig(:credit, code).nil? ? 0 : Util.calc_diff(g[:credit][code], code)
|
277
|
+
count[code] = (g.dig(:debit_count, code) || 0) + (g.dig(:credit_count, code) || 0)
|
217
278
|
end
|
218
279
|
end
|
280
|
+
[diff, count]
|
219
281
|
end
|
220
282
|
|
221
283
|
# TODO: replace load_tsv -> generic load_tsv_dict
|
222
284
|
def load_start
|
223
|
-
file = LucaSupport::Config::Pjdir
|
285
|
+
file = Pathname(LucaSupport::Config::Pjdir) / 'data' / 'balance' / 'start.tsv'
|
224
286
|
{}.tap do |dic|
|
225
287
|
load_tsv(file) do |row|
|
226
288
|
dic[row[0]] = row[2].to_i if ! row[2].nil?
|
@@ -235,24 +297,15 @@ module LucaBook
|
|
235
297
|
data.each { |row| yield row }
|
236
298
|
end
|
237
299
|
|
238
|
-
|
239
|
-
amount = /\./.match(num.to_s) ? BigDecimal(num) : num.to_i
|
240
|
-
amount * pn_debit(code.to_s)
|
241
|
-
end
|
300
|
+
private
|
242
301
|
|
243
|
-
def
|
244
|
-
|
245
|
-
when /^[0-4BCEGH]/
|
246
|
-
1
|
247
|
-
when /^[5-9ADF]/
|
248
|
-
-1
|
249
|
-
else
|
250
|
-
nil
|
251
|
-
end
|
252
|
-
end
|
302
|
+
def legal_items
|
303
|
+
return [] unless LucaSupport::Config::COUNTRY
|
253
304
|
|
254
|
-
|
255
|
-
|
305
|
+
case LucaSupport::Config::COUNTRY
|
306
|
+
when 'jp'
|
307
|
+
['91', '911', '912', '913', '9131', '9132', '914', '9141', '9142', '915', '916', '92', '93']
|
308
|
+
end
|
256
309
|
end
|
257
310
|
end
|
258
311
|
end
|