lucabook 0.2.27 → 0.2.31
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 +32 -6
- data/lib/luca_book/accumulator.rb +62 -10
- data/lib/luca_book/dict.rb +29 -12
- data/lib/luca_book/import.rb +3 -1
- data/lib/luca_book/list.rb +118 -3
- data/lib/luca_book/list_by_header.rb +3 -11
- data/lib/luca_book/state.rb +13 -9
- data/lib/luca_book/templates/dict-jp-edinet.tsv +1 -1
- data/lib/luca_book/templates/dict-jp.tsv +1 -1
- data/lib/luca_book/templates/journals.html.erb +23 -0
- data/lib/luca_book/test.rb +17 -0
- data/lib/luca_book/util.rb +10 -0
- data/lib/luca_book/version.rb +1 -1
- data/lib/luca_book.rb +1 -0
- metadata +9 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 87936c519f40b82f1559b0cc20820e3f3a8b8d8afde4914ca1b8f749db5b69a0
|
4
|
+
data.tar.gz: 9dfc82e16185a42f2ea8e598b69a7f7448fb8aeae55d831ac72617980982e037
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f388153393b76ff871c6c8e028efeaf4476400608ec7b100c81bb1a39f0bf8efc67fa3b79d7d0e987bc8565e41c4098109164a7afe873baa816fafa2ca564ed7
|
7
|
+
data.tar.gz: 4701eb25e02571465d4ed053f1f17ee361a36f5420589dff1396f6adf1267d89e9f4de0c90fb812b45e549109da1fd0a93ce8133b007f0864120b64518037652
|
data/exe/luca-book
CHANGED
@@ -19,13 +19,15 @@ class LucaCmd
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.list(args, params)
|
22
|
-
args = gen_range(params[:n]
|
22
|
+
args = gen_range(params[:n]) if args.empty?
|
23
23
|
if params['code']
|
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
27
|
render(LucaBook::List.term(*args, code: params['code'], recursive: params[:recursive]).list_by_code(params[:recursive]), params)
|
28
28
|
end
|
29
|
+
elsif params['render']
|
30
|
+
puts LucaBook::List.term(*args).render_html(params['render'])
|
29
31
|
else
|
30
32
|
render(LucaBook::List.term(*args).list_journals, params)
|
31
33
|
end
|
@@ -78,11 +80,19 @@ class LucaCmd
|
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
81
|
-
def self.gen_range(count)
|
82
|
-
count ||= 3
|
83
|
+
def self.gen_range(count = nil)
|
83
84
|
today = Date.today
|
84
|
-
|
85
|
-
|
85
|
+
if count
|
86
|
+
start = today.prev_month(count - 1)
|
87
|
+
[start.year, start.month, today.year, today.month]
|
88
|
+
else
|
89
|
+
start_year = if today.month >= LucaSupport::CONFIG['fy_start'].to_i
|
90
|
+
today.year
|
91
|
+
else
|
92
|
+
today.year - 1
|
93
|
+
end
|
94
|
+
[start_year, LucaSupport::CONFIG['fy_start'], start_year + 1, LucaSupport::CONFIG['fy_start'].to_i - 1]
|
95
|
+
end
|
86
96
|
end
|
87
97
|
|
88
98
|
def self.render(dat, params)
|
@@ -100,6 +110,11 @@ class LucaCmd
|
|
100
110
|
def self.update_balance(args, params)
|
101
111
|
LucaBook::Dict.generate_balance(*args)
|
102
112
|
end
|
113
|
+
|
114
|
+
def self.export_balance(args, params)
|
115
|
+
date = Date.new(args[0].to_i, args[1].to_i, args[2].to_i)
|
116
|
+
LucaBook::Dict.export_balance(date)
|
117
|
+
end
|
103
118
|
end
|
104
119
|
end
|
105
120
|
|
@@ -133,6 +148,8 @@ when /journals?/, 'j'
|
|
133
148
|
opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
|
134
149
|
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
135
150
|
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
151
|
+
opt.on('--html', 'output journals html') { |_v| params['render'] = :html }
|
152
|
+
opt.on('--pdf', 'output journals PDF') { |_v| params['render'] = :pdf }
|
136
153
|
opt.on_tail('List records. If you specify code and/or month, search on each criteria.')
|
137
154
|
args = opt.parse!(ARGV)
|
138
155
|
LucaCmd::Journal.list(args, params)
|
@@ -216,9 +233,11 @@ when /reports?/, 'r'
|
|
216
233
|
else
|
217
234
|
puts 'Proper subcommand needed.'
|
218
235
|
puts
|
219
|
-
puts 'Usage: luca-book (r|report[s]) (bs|pl) [options] YYYY M'
|
236
|
+
puts 'Usage: luca-book (r|report[s]) (bs|pl|mail|xbrl) [options] YYYY M'
|
220
237
|
puts ' bs: show balance sheet'
|
221
238
|
puts ' pl: show statement of income'
|
239
|
+
puts ' mail: send BS/PL via email'
|
240
|
+
puts ' xbrl: render XBRL report'
|
222
241
|
exit 1
|
223
242
|
end
|
224
243
|
when /balance/
|
@@ -230,6 +249,12 @@ when /balance/
|
|
230
249
|
args = opt.parse!(ARGV)
|
231
250
|
LucaCmd::Dict.update_balance(args, params)
|
232
251
|
end
|
252
|
+
when 'export'
|
253
|
+
OptionParser.new do |opt|
|
254
|
+
opt.banner = 'Usage: luca-book balance export YYYY M d'
|
255
|
+
args = opt.parse!(ARGV)
|
256
|
+
LucaCmd::Dict.export_balance(args, params)
|
257
|
+
end
|
233
258
|
end
|
234
259
|
else
|
235
260
|
puts 'Proper subcommand needed.'
|
@@ -237,5 +262,6 @@ else
|
|
237
262
|
puts 'Usage: luca-book (j[ournals]|r[eports]) subcommand'
|
238
263
|
puts ' journals: operate journal records'
|
239
264
|
puts ' reports: show reports'
|
265
|
+
puts ' balance update: generate accumulated balance'
|
240
266
|
exit 1
|
241
267
|
end
|
@@ -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,
|
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
|
@@ -84,7 +84,7 @@ module LucaBook
|
|
84
84
|
end_month ||= start_month
|
85
85
|
sum = { debit: {}, credit: {}, debit_count: {}, credit_count: {} }
|
86
86
|
idx_memo = []
|
87
|
-
term(start_year, start_month, end_year, end_month, code) do |f, _path|
|
87
|
+
term(start_year, start_month, end_year, end_month, code, 'journals') do |f, _path|
|
88
88
|
CSV.new(f, headers: false, col_sep: "\t", encoding: 'UTF-8')
|
89
89
|
.each_with_index do |row, i|
|
90
90
|
break if i >= rows
|
@@ -130,20 +130,20 @@ module LucaBook
|
|
130
130
|
else
|
131
131
|
Array(code)
|
132
132
|
end
|
133
|
-
res = { debit: 0, credit: 0, debit_count: 0, credit_count: 0 }
|
134
|
-
codes.each do |
|
135
|
-
res[:debit] += sum[:debit][
|
136
|
-
res[:credit] += sum[:credit][
|
137
|
-
res[:debit_count] += sum[:debit_count][
|
138
|
-
res[:credit_count] += sum[:credit_count][
|
133
|
+
res = { debit: { code => 0 }, credit: { code => 0 }, debit_count: { code => 0 }, credit_count: { code => 0 } }
|
134
|
+
codes.each do |cd|
|
135
|
+
res[:debit][code] += sum[:debit][cd] || BigDecimal('0')
|
136
|
+
res[:credit][code] += sum[:credit][cd] || BigDecimal('0')
|
137
|
+
res[:debit_count][code] += sum[:debit_count][cd] || 0
|
138
|
+
res[:credit_count][code] += sum[:credit_count][cd] || 0
|
139
139
|
end
|
140
140
|
res
|
141
141
|
end
|
142
142
|
|
143
143
|
# netting vouchers in specified term
|
144
144
|
#
|
145
|
-
def net(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil)
|
146
|
-
g = gross(start_year, start_month, end_year, end_month, code: code, date_range: date_range)
|
145
|
+
def net(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil, recursive: false)
|
146
|
+
g = gross(start_year, start_month, end_year, end_month, code: code, date_range: date_range, recursive: recursive)
|
147
147
|
idx = (g[:debit].keys + g[:credit].keys).uniq.sort
|
148
148
|
count = {}
|
149
149
|
diff = {}.tap do |sum|
|
@@ -155,6 +155,58 @@ module LucaBook
|
|
155
155
|
end
|
156
156
|
[diff, count]
|
157
157
|
end
|
158
|
+
|
159
|
+
# Override LucaRecord::IO.load_data
|
160
|
+
#
|
161
|
+
def load_data(io, path = nil)
|
162
|
+
io
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def net_amount(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
167
|
+
start_year ||= @cursor_start&.year || @start_date.year
|
168
|
+
start_month ||= @cursor_start&.month || @start_date.month
|
169
|
+
end_year ||= @cursor_end&.year || @end_date.year
|
170
|
+
end_month ||= @cursor_end&.month || @end_date.month
|
171
|
+
self.class.net(start_year, start_month, end_year, end_month, code: code, recursive: recursive)[0][code]
|
172
|
+
end
|
173
|
+
|
174
|
+
def debit_amount(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
175
|
+
gross_amount(code, start_year, start_month, end_year, end_month, recursive: recursive)[0]
|
176
|
+
end
|
177
|
+
|
178
|
+
def credit_amount(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
179
|
+
gross_amount(code, start_year, start_month, end_year, end_month, recursive: recursive)[1]
|
180
|
+
end
|
181
|
+
|
182
|
+
def gross_amount(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
183
|
+
start_year ||= @cursor_start&.year || @start_date.year
|
184
|
+
start_month ||= @cursor_start&.month || @start_date.month
|
185
|
+
end_year ||= @cursor_end&.year || @end_date.year
|
186
|
+
end_month ||= @cursor_end&.month || @end_date.month
|
187
|
+
g = self.class.gross(start_year, start_month, end_year, end_month, code: code, recursive: recursive)
|
188
|
+
[g[:debit][code], g[:credit][code]]
|
189
|
+
end
|
190
|
+
|
191
|
+
def debit_count(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
192
|
+
gross_count(code, start_year, start_month, end_year, end_month, recursive: recursive)[0]
|
193
|
+
end
|
194
|
+
|
195
|
+
def credit_count(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
196
|
+
gross_count(code, start_year, start_month, end_year, end_month, recursive: recursive)[1]
|
197
|
+
end
|
198
|
+
|
199
|
+
def gross_count(code, start_year = nil, start_month = nil, end_year = nil, end_month = nil, recursive: true)
|
200
|
+
start_year ||= @cursor_start&.year || @start_date.year
|
201
|
+
start_month ||= @cursor_start&.month || @start_date.month
|
202
|
+
end_year ||= @cursor_end&.year || @end_date.year
|
203
|
+
end_month ||= @cursor_end&.month || @end_date.month
|
204
|
+
g = self.class.gross(start_year, start_month, end_year, end_month, code: code, recursive: recursive)
|
205
|
+
[g[:debit_count][code], g[:credit_count][code]]
|
206
|
+
end
|
207
|
+
|
208
|
+
def each_month
|
209
|
+
yield
|
158
210
|
end
|
159
211
|
end
|
160
212
|
end
|
data/lib/luca_book/dict.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'luca_support/code'
|
4
4
|
require 'luca_support/config'
|
5
|
+
require 'luca_support/range'
|
5
6
|
require 'luca_record/dict'
|
6
7
|
require 'luca_record/io'
|
7
8
|
require 'luca_book'
|
@@ -10,11 +11,12 @@ require 'pathname'
|
|
10
11
|
|
11
12
|
module LucaBook
|
12
13
|
class Dict < LucaRecord::Dict
|
13
|
-
include
|
14
|
+
include LucaSupport::Range
|
15
|
+
include LucaBook::Util
|
14
16
|
include LucaRecord::IO
|
17
|
+
include Accumulator
|
15
18
|
|
16
19
|
@dirname = 'journals'
|
17
|
-
@record_type = 'raw'
|
18
20
|
# Column number settings for CSV/TSV convert
|
19
21
|
#
|
20
22
|
# :label
|
@@ -137,6 +139,31 @@ module LucaBook
|
|
137
139
|
File.open(filepath, 'w') { |f| f.write csv }
|
138
140
|
end
|
139
141
|
|
142
|
+
# TODO: support date in the middle of month.
|
143
|
+
def self.export_balance(date)
|
144
|
+
start_date, end_date = Util.current_fy(date, to: date)
|
145
|
+
labels = load('base.tsv')
|
146
|
+
bs = load_balance(start_date, end_date)
|
147
|
+
dat = [].tap do |res|
|
148
|
+
item = {}
|
149
|
+
item['date'] = date.to_s
|
150
|
+
item['debit'] = []
|
151
|
+
item['credit'] = []
|
152
|
+
bs.each do |code, balance|
|
153
|
+
next if balance.zero?
|
154
|
+
|
155
|
+
if /^[1-4]/.match(code)
|
156
|
+
item['debit'] << { 'label' => labels.dig(code, :label), 'amount' => LucaSupport::Code.readable(balance) }
|
157
|
+
elsif /^[5-9]/.match(code)
|
158
|
+
item['credit'] << { 'label' => labels.dig(code, :label), 'amount' => LucaSupport::Code.readable(balance) }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
item['x-editor'] = 'LucaBook'
|
162
|
+
res << item
|
163
|
+
end
|
164
|
+
puts JSON.dump(dat)
|
165
|
+
end
|
166
|
+
|
140
167
|
def self.load_balance(start_date, end_date)
|
141
168
|
base = latest_balance(start_date).each_with_object({}) do |(k, v), h|
|
142
169
|
h[k] = BigDecimal(v[:balance].to_s) if v[:balance]
|
@@ -170,15 +197,5 @@ module LucaBook
|
|
170
197
|
digest = `git rev-parse HEAD`
|
171
198
|
$?.exitstatus == 0 ? digest.strip : nil
|
172
199
|
end
|
173
|
-
|
174
|
-
def self.term_by_month(start_date, end_date)
|
175
|
-
Enumerator.new do |yielder|
|
176
|
-
each_month = start_date
|
177
|
-
while each_month <= end_date
|
178
|
-
yielder << each_month
|
179
|
-
each_month = each_month.next_month
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
183
200
|
end
|
184
201
|
end
|
data/lib/luca_book/import.rb
CHANGED
@@ -81,7 +81,7 @@ module LucaBook
|
|
81
81
|
else
|
82
82
|
amount = BigDecimal(row[@config[:credit_amount]])
|
83
83
|
end
|
84
|
-
default_label = debit ? @config
|
84
|
+
default_label = debit ? @config[:default_debit] : @config[:default_credit]
|
85
85
|
code, options = search_code(row[@config[:label]], default_label, amount)
|
86
86
|
counter_code = @code_map.dig(@config[:counter_label])
|
87
87
|
if options
|
@@ -94,10 +94,12 @@ module LucaBook
|
|
94
94
|
d['date'] = parse_date(row)
|
95
95
|
if debit
|
96
96
|
d['debit'] = data
|
97
|
+
d['debit'][0]['code'] ||= DEBIT_DEFAULT
|
97
98
|
d['credit'] = data_c
|
98
99
|
else
|
99
100
|
d['debit'] = data_c
|
100
101
|
d['credit'] = data
|
102
|
+
d['credit'][0]['code'] ||= CREDIT_DEFAULT
|
101
103
|
end
|
102
104
|
d['note'] = Array(@config[:note]).map{ |col| row[col] }.join(' ')
|
103
105
|
d['headers'] = { 'x-editor' => "LucaBook::Import/#{@dict_name}" }
|
data/lib/luca_book/list.rb
CHANGED
@@ -101,16 +101,127 @@ module LucaBook #:nodoc:
|
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
+
def render_html(file_type = :html)
|
105
|
+
start_balance = set_balance(true)
|
106
|
+
@journals = group_by_code.map do |account|
|
107
|
+
balance = start_balance[account[:code]] || BigDecimal('0')
|
108
|
+
table = []
|
109
|
+
table << %Q(<h2 class="title">#{@@dict.dig(account[:code], :label)}</h2>)
|
110
|
+
|
111
|
+
account[:vouchers].map { |voucher| filter_by_code(voucher, account[:code]) }.flatten
|
112
|
+
.unshift({ balance: readable(balance) })
|
113
|
+
.map { |row|
|
114
|
+
balance += Util.pn_debit(account[:code]) * ((row.dig(:amount, :debit) || 0) - (row.dig(:amount, :credit) || 0))
|
115
|
+
row[:balance] = readable(balance)
|
116
|
+
row
|
117
|
+
}
|
118
|
+
.map { |row| render_line(row) }
|
119
|
+
.each_slice(28) do |rows|
|
120
|
+
table << table_header
|
121
|
+
table << rows.join("\n")
|
122
|
+
table << table_footer
|
123
|
+
table << %Q(<hr class='pgbr' />)
|
124
|
+
end
|
125
|
+
table[0..-2].join("\n")
|
126
|
+
end
|
127
|
+
|
128
|
+
case file_type
|
129
|
+
when :html
|
130
|
+
render_erb(search_template('journals.html.erb'))
|
131
|
+
when :pdf
|
132
|
+
erb2pdf(search_template('journals.html.erb'))
|
133
|
+
else
|
134
|
+
raise 'This filetype is not supported.'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def table_header
|
139
|
+
%Q(<table>
|
140
|
+
<thead>
|
141
|
+
<th>Date<br />No</th>
|
142
|
+
<th>Counter account</th>
|
143
|
+
<th>Sub account<br />Note</th>
|
144
|
+
<th>Debit</th>
|
145
|
+
<th>Credit</th>
|
146
|
+
<th>Balance</th>
|
147
|
+
</thead>
|
148
|
+
<tbody>)
|
149
|
+
end
|
150
|
+
|
151
|
+
def table_footer
|
152
|
+
%Q(</tbody>
|
153
|
+
</table>)
|
154
|
+
end
|
155
|
+
|
156
|
+
def filter_by_code(voucher, code)
|
157
|
+
[:debit, :credit].each_with_object([]) do |balance, lines|
|
158
|
+
voucher[balance].each do |record|
|
159
|
+
next unless /^#{code}/.match(record[:code])
|
160
|
+
|
161
|
+
counter_balance = (balance == :debit) ? :credit : :debit
|
162
|
+
view = { code: record[:code], amount: {} }
|
163
|
+
view[:date], view[:txid] = decode_id(voucher[:id])
|
164
|
+
view[:label] = @@dict.dig(record[:code], :label) if record[:code].length >= 4
|
165
|
+
view[:label] = voucher.dig(:headers, 'x-customer') if view[:label].nil?
|
166
|
+
view[:amount][balance] = readable(record[:amount])
|
167
|
+
view[:counter_code] = voucher.dig(counter_balance, 0, :code)
|
168
|
+
view[:counter_label] = @@dict.dig(view[:counter_code], :label) || ''
|
169
|
+
view[:counter_label] += ' sundry a/c' if voucher[counter_balance].length > 1
|
170
|
+
view[:note] = voucher[:note]
|
171
|
+
lines << view
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def render_line(view)
|
177
|
+
%Q(<tr>
|
178
|
+
<td class="date">#{view[:date]}<br /><div>#{view[:txid]}</div></td>
|
179
|
+
<td class="counter">#{view[:counter_label]}</td>
|
180
|
+
<td class="note">#{view[:label]}<br /><div class="note">#{view[:note]}</div></td>
|
181
|
+
<td class="debit amount">#{view.dig(:amount, :debit)}</td>
|
182
|
+
<td class="credit amount">#{view.dig(:amount, :credit)}</td>
|
183
|
+
<td class="balance">#{view[:balance]}</td>
|
184
|
+
</tr>)
|
185
|
+
end
|
186
|
+
|
187
|
+
def group_by_code(level = 3)
|
188
|
+
list_accounts.map do |code|
|
189
|
+
vouchers = @data.filter do |voucher|
|
190
|
+
codes = [:debit, :credit].map do |balance|
|
191
|
+
voucher[balance].map { |record| record[:code][0, level] }
|
192
|
+
end
|
193
|
+
codes.flatten.include?(code)
|
194
|
+
end
|
195
|
+
{ code: code, vouchers: vouchers }
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def list_accounts(level = 3)
|
200
|
+
return nil if level < 3
|
201
|
+
|
202
|
+
list = @data.each_with_object([]) do |voucher, codes|
|
203
|
+
[:debit, :credit].each do |balance|
|
204
|
+
voucher[balance].each do |record|
|
205
|
+
next if record[:code].length < level
|
206
|
+
|
207
|
+
codes << record[:code][0, level]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
list.uniq.sort
|
212
|
+
end
|
213
|
+
|
104
214
|
private
|
105
215
|
|
106
216
|
def set_balance(recursive = false)
|
107
|
-
return
|
217
|
+
return LucaBook::State.start_balance(@start.year, @start.month, recursive: recursive) if @code.nil?
|
218
|
+
return BigDecimal('0') if /^[A-H]/.match(@code)
|
108
219
|
|
109
|
-
LucaBook::State.start_balance(@start.year, @start.month, recursive: recursive)
|
220
|
+
LucaBook::State.start_balance(@start.year, @start.month, recursive: recursive)[@code] || BigDecimal('0')
|
110
221
|
end
|
111
222
|
|
112
223
|
def calc_code(recursive: false)
|
113
|
-
@balance = set_balance(recursive)
|
224
|
+
@balance = set_balance(recursive)
|
114
225
|
if @code
|
115
226
|
balance = @balance
|
116
227
|
@data.each do |dat|
|
@@ -145,5 +256,9 @@ module LucaBook #:nodoc:
|
|
145
256
|
end
|
146
257
|
end
|
147
258
|
end
|
259
|
+
|
260
|
+
def lib_path
|
261
|
+
__dir__
|
262
|
+
end
|
148
263
|
end
|
149
264
|
end
|
@@ -49,7 +49,7 @@ module LucaBook #:nodoc:
|
|
49
49
|
res['note'] = dat[:note]
|
50
50
|
end
|
51
51
|
end
|
52
|
-
a << { 'code' => v.last[:code], 'header' => k, 'balance' => v.last[:balance], 'count' => v.count, '
|
52
|
+
a << { 'code' => v.last[:code], 'header' => k, 'balance' => v.last[:balance], 'count' => v.count, 'journals' => journals }
|
53
53
|
end
|
54
54
|
readable(@data)
|
55
55
|
end
|
@@ -67,16 +67,8 @@ module LucaBook #:nodoc:
|
|
67
67
|
def set_balance
|
68
68
|
return BigDecimal('0') if @code.nil? || /^[A-H]/.match(@code)
|
69
69
|
|
70
|
-
|
71
|
-
start_balance
|
72
|
-
start = Dict.issue_date(balance_dict)&.next_month
|
73
|
-
last = @start.prev_month
|
74
|
-
if last.year >= start.year && last.month >= start.month
|
75
|
-
#TODO: start_balance to be implemented by header
|
76
|
-
self.class.term(start.year, start.month, last.year, last.month, code: @code).accumulate_code
|
77
|
-
else
|
78
|
-
#start_balance
|
79
|
-
end
|
70
|
+
#TODO: start_balance to be implemented by header
|
71
|
+
LucaBook::State.start_balance(@start.year, @start.month)
|
80
72
|
end
|
81
73
|
|
82
74
|
def calc_code
|
data/lib/luca_book/state.rb
CHANGED
@@ -17,7 +17,6 @@ module LucaBook
|
|
17
17
|
include Accumulator
|
18
18
|
|
19
19
|
@dirname = 'journals'
|
20
|
-
@record_type = 'raw'
|
21
20
|
@@dict = LucaRecord::Dict.new('base.tsv')
|
22
21
|
|
23
22
|
attr_reader :statement, :pl_data, :bs_data, :start_balance
|
@@ -62,15 +61,15 @@ module LucaBook
|
|
62
61
|
while date <= last_date do
|
63
62
|
diff = {}.tap do |h|
|
64
63
|
g = gross(date.year, date.month, code: code, recursive: recursive)
|
65
|
-
sum = g.dig(:debit).nil? ? BigDecimal('0') : Util.calc_diff(g[:debit], code)
|
66
|
-
sum -= g.dig(:credit).nil? ? BigDecimal('0') : Util.calc_diff(g[:credit], code)
|
64
|
+
sum = g.dig(:debit, code).nil? ? BigDecimal('0') : Util.calc_diff(g[:debit][code], code)
|
65
|
+
sum -= g.dig(:credit, code).nil? ? BigDecimal('0') : Util.calc_diff(g[:credit][code], code)
|
67
66
|
balance += sum
|
68
67
|
h['code'] = code
|
69
68
|
h['label'] = @@dict.dig(code, :label)
|
70
|
-
h['debit_amount'] = g
|
71
|
-
h['debit_count'] = g
|
72
|
-
h['credit_amount'] = g
|
73
|
-
h['credit_count'] = g
|
69
|
+
h['debit_amount'] = g.dig(:debit, code)
|
70
|
+
h['debit_count'] = g.dig(:debit_count, code)
|
71
|
+
h['credit_amount'] = g.dig(:credit, code)
|
72
|
+
h['credit_count'] = g.dig(:credit_count, code)
|
74
73
|
h['net'] = sum
|
75
74
|
h['balance'] = balance
|
76
75
|
h['_d'] = date.to_s
|
@@ -147,7 +146,7 @@ module LucaBook
|
|
147
146
|
res['debit_label'] = base[:debit][i] ? @@dict.dig(base[:debit][i].keys[0], :label) : ''
|
148
147
|
#res['debit_balance'] = base[:debit][i] ? (@start_balance.dig(base[:debit][i].keys[0]) || 0) + base[:debit][i].values[0] : ''
|
149
148
|
res['debit_balance'] = base[:debit][i] ? base[:debit][i].values[0] : ''
|
150
|
-
res['credit_label'] = base[:credit][i] ?
|
149
|
+
res['credit_label'] = base[:credit][i] ? @@dict.dig(base[:credit][i].keys[0], :label) : ''
|
151
150
|
#res['credit_balance'] = base[:credit][i] ? (@start_balance.dig(base[:credit][i].keys[0]) || 0) + base[:credit][i].values[0] : ''
|
152
151
|
res['credit_balance'] = base[:credit][i] ? base[:credit][i].values[0] : ''
|
153
152
|
a << res
|
@@ -233,6 +232,7 @@ module LucaBook
|
|
233
232
|
recursive ? total_subaccount(total) : total
|
234
233
|
end
|
235
234
|
|
235
|
+
# TODO: currency setting other than JPY
|
236
236
|
def render_xbrl(filename = nil)
|
237
237
|
set_bs(3, legal: true)
|
238
238
|
set_pl(3)
|
@@ -261,7 +261,11 @@ module LucaBook
|
|
261
261
|
return nil if tag.nil?
|
262
262
|
return nil if readable(amount).zero? && prior_amount.nil?
|
263
263
|
|
264
|
-
prior = prior_amount.nil?
|
264
|
+
prior = if prior_amount.nil?
|
265
|
+
/^[9]/.match(code) ? "<#{tag} decimals=\"0\" unitRef=\"JPY\" contextRef=\"Prior1YearNonConsolidatedInstant\">0</#{tag}>\n" : ''
|
266
|
+
else
|
267
|
+
"<#{tag} decimals=\"0\" unitRef=\"JPY\" contextRef=\"Prior1YearNonConsolidatedInstant\">#{readable(prior_amount)}</#{tag}>\n"
|
268
|
+
end
|
265
269
|
current = "<#{tag} decimals=\"0\" unitRef=\"JPY\" contextRef=\"#{context}\">#{readable(amount)}</#{tag}>"
|
266
270
|
|
267
271
|
prior + current
|
@@ -82,7 +82,7 @@ code label xbrl_id consumption_tax income_tax
|
|
82
82
|
91 株主資本 jppfs_cor:ShareholdersAbstract
|
83
83
|
911 資本金 jppfs_cor:CapitalStock
|
84
84
|
912 新株式申込証拠金 jppfs_cor:DepositForSubscriptionsToShares
|
85
|
-
913 資本剰余金 jppfs_cor:
|
85
|
+
913 資本剰余金 jppfs_cor:CapitalSurplus
|
86
86
|
9131 資本準備金 jppfs_cor:LegalCapitalSurplus
|
87
87
|
9132 その他資本剰余金 jppfs_cor:OtherCapitalSurplus
|
88
88
|
914 利益剰余金 jppfs_cor:RetainedEarnings
|
@@ -105,7 +105,7 @@ code label xbrl_id consumption_tax income_tax
|
|
105
105
|
91 株主資本 jpfr-t-cte:ShareholdersEquity
|
106
106
|
911 資本金 jpfr-t-cte:CapitalStock
|
107
107
|
912 新株式申込証拠金 jpfr-t-cte:DepositForSubscriptionsToShares
|
108
|
-
913 資本剰余金 jpfr-t-cte:
|
108
|
+
913 資本剰余金 jpfr-t-cte:CapitalSurplus
|
109
109
|
9131 資本準備金 jpfr-t-cte:LegalCapitalSurplus
|
110
110
|
9132 その他資本剰余金 jpfr-t-cte:OtherCapitalSurplus
|
111
111
|
914 繰越利益剰余金 jpfr-t-cte:RetainedEarningsBroughtForward
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<meta charset="utf-8">
|
4
|
+
<style>
|
5
|
+
body { size: A4; padding-top: 2em; padding-bottom: 2em }
|
6
|
+
.pgbr { page-break-after: always; visibility: hidden }
|
7
|
+
.title { margin-bottom: 1.5rem; text-align: center }
|
8
|
+
div.note { font-size: .8em }
|
9
|
+
table { border-collapse: collapse; max-width: 92%; margin: 1em auto }
|
10
|
+
th, td { border-bottom: solid 1px #555; }
|
11
|
+
td div { break-before: avoid-page; break-after: avoid-page; break-inside: avoid-page }
|
12
|
+
td { padding-top: .3em; padding-bottom: .3em; break-inside: avoid-page }
|
13
|
+
td.date { min-width: 7em; text-align: right; padding-right: 1em }
|
14
|
+
td.counter { min-width: 8.5em; padding-right: .5em }
|
15
|
+
td.note { min-width: 12em }
|
16
|
+
td.amount { text-align: right; min-width: 7em }
|
17
|
+
td.balance { text-align: right; min-width: 10em; padding-right: 1em }
|
18
|
+
</style>
|
19
|
+
</head>
|
20
|
+
<body>
|
21
|
+
<%= @journals.join("<hr class='pgbr' />\n") %>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'luca_book'
|
5
|
+
require 'luca_record/io'
|
6
|
+
require 'luca_support/range'
|
7
|
+
|
8
|
+
module LucaBook # :nodoc:
|
9
|
+
# Provide data testing framework utilizing minitest.
|
10
|
+
#
|
11
|
+
class Test < MiniTest::Test
|
12
|
+
include LucaSupport::Range
|
13
|
+
include LucaRecord::IO
|
14
|
+
include LucaBook::Accumulator
|
15
|
+
include LucaBook::Util
|
16
|
+
end
|
17
|
+
end
|
data/lib/luca_book/util.rb
CHANGED
@@ -42,5 +42,15 @@ module LucaBook
|
|
42
42
|
nil
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
def current_fy(date = nil, to: nil)
|
47
|
+
date ||= Date.today
|
48
|
+
start_month = LucaSupport::CONFIG['fy_start']
|
49
|
+
start_year = date.month >= start_month ? date.year : date.year - 1
|
50
|
+
@start_date = Date.new(start_year, start_month, 1)
|
51
|
+
@end_date = Date.new(start_year + 1, start_month - 1, -1)
|
52
|
+
@end_date = [to, @end_date].min if to
|
53
|
+
[@start_date, @end_date]
|
54
|
+
end
|
45
55
|
end
|
46
56
|
end
|
data/lib/luca_book/version.rb
CHANGED
data/lib/luca_book.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lucabook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.31
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lucarecord
|
@@ -68,7 +68,7 @@ dependencies:
|
|
68
68
|
version: 12.3.3
|
69
69
|
description: 'Book keep
|
70
70
|
|
71
|
-
'
|
71
|
+
'
|
72
72
|
email:
|
73
73
|
- co.chuma@gmail.com
|
74
74
|
executables:
|
@@ -95,7 +95,9 @@ files:
|
|
95
95
|
- lib/luca_book/templates/dict-en.tsv
|
96
96
|
- lib/luca_book/templates/dict-jp-edinet.tsv
|
97
97
|
- lib/luca_book/templates/dict-jp.tsv
|
98
|
+
- lib/luca_book/templates/journals.html.erb
|
98
99
|
- lib/luca_book/templates/monthly-report.html.erb
|
100
|
+
- lib/luca_book/test.rb
|
99
101
|
- lib/luca_book/util.rb
|
100
102
|
- lib/luca_book/version.rb
|
101
103
|
homepage: https://github.com/chumaltd/luca/tree/master/lucabook
|
@@ -104,7 +106,7 @@ licenses:
|
|
104
106
|
metadata:
|
105
107
|
homepage_uri: https://github.com/chumaltd/luca/tree/master/lucabook
|
106
108
|
source_code_uri: https://github.com/chumaltd/luca/tree/master/lucabook
|
107
|
-
post_install_message:
|
109
|
+
post_install_message:
|
108
110
|
rdoc_options: []
|
109
111
|
require_paths:
|
110
112
|
- lib
|
@@ -119,8 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
121
|
- !ruby/object:Gem::Version
|
120
122
|
version: '0'
|
121
123
|
requirements: []
|
122
|
-
rubygems_version: 3.2.
|
123
|
-
signing_key:
|
124
|
+
rubygems_version: 3.2.5
|
125
|
+
signing_key:
|
124
126
|
specification_version: 4
|
125
127
|
summary: Book keep
|
126
128
|
test_files: []
|