lucabook 0.2.17 → 0.2.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/luca-book +77 -22
- data/lib/luca_book/dict.rb +77 -0
- data/lib/luca_book/import.rb +29 -32
- data/lib/luca_book/import_jp.rb +83 -0
- data/lib/luca_book/journal.rb +17 -0
- data/lib/luca_book/list.rb +2 -6
- data/lib/luca_book/state.rb +144 -98
- data/lib/luca_book/templates/dict-en.tsv +30 -23
- data/lib/luca_book/templates/dict-jp.tsv +18 -13
- data/lib/luca_book/version.rb +1 -1
- metadata +3 -3
- data/lib/luca_book/report.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4755b2574729e35ae914dd92338ed007df2e1158d49c613613cac3b42423c6ee
|
4
|
+
data.tar.gz: a559a270322897b10b6dae569102f028004221431300debe19f3d0e5ae6432fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34b28c364e41ddecf9296ef39130897f03228e0bb0184241e0a7fce4349d41b14ff0ea72318154eb0bfa5e8fdac401783851c61e34e3419620eac6ab12cf6b05
|
7
|
+
data.tar.gz: 1bbd862143cc37ba7c459a6d3fae832bbdad744b1db6afc3956175fa97660a1decf8a778c6c40c3e276dd35272ed363f5d9e575ce555b73a368cf2ef8173fcbf
|
data/exe/luca-book
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
|
3
|
+
require 'json'
|
3
4
|
require 'optparse'
|
4
5
|
require 'luca_book'
|
5
6
|
|
6
|
-
|
7
|
-
class Journal
|
7
|
+
class LucaCmd
|
8
|
+
class Journal < LucaCmd
|
8
9
|
def self.import(args, params)
|
9
10
|
if params['config']
|
10
11
|
LucaBook::Import.new(args[0], params['config']).import_csv
|
@@ -12,33 +13,59 @@ module LucaCmd
|
|
12
13
|
LucaBook::Import.import_json(STDIN.read)
|
13
14
|
else
|
14
15
|
puts 'Usage: luca-book import -c import_config'
|
16
|
+
exit 1
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.list(args, params)
|
21
|
+
args = gen_range(params[:n] || 1) if args.empty?
|
19
22
|
if params['code']
|
20
|
-
LucaBook::List.term(*args, code: params['code']).list_on_code
|
21
|
-
elsif args.length > 0
|
22
|
-
LucaBook::List.term(*args).list_journals.to_yaml
|
23
|
+
render(LucaBook::List.term(*args, code: params['code']).list_on_code, params)
|
23
24
|
else
|
24
|
-
|
25
|
+
render(LucaBook::List.term(*args).list_journals, params)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.stats(args, params)
|
29
|
-
|
30
|
+
args = gen_range(params[:n]) if args.empty?
|
31
|
+
if params['code']
|
32
|
+
render(LucaBook::State.by_code(params['code'], *args), params)
|
33
|
+
else
|
34
|
+
render(LucaBook::State.range(*args).stats(params[:level]), params)
|
35
|
+
end
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
|
-
class Report
|
39
|
+
class Report < LucaCmd
|
34
40
|
def self.balancesheet(args, params)
|
35
|
-
level = params[:level] ||
|
41
|
+
level = params[:level] || 3
|
36
42
|
legal = params[:legal] || false
|
37
|
-
|
43
|
+
args = gen_range(params[:n] || 1) if args.empty?
|
44
|
+
render(LucaBook::State.range(*args).bs(level, legal: legal), params)
|
38
45
|
end
|
39
46
|
|
40
47
|
def self.profitloss(args, params)
|
41
|
-
|
48
|
+
level = params[:level] || 2
|
49
|
+
args = gen_range(params[:n]) if args.empty?
|
50
|
+
render(LucaBook::State.range(*args).pl(level), params)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.gen_range(count)
|
55
|
+
count ||= 3
|
56
|
+
today = Date.today
|
57
|
+
start = today.prev_month(count - 1)
|
58
|
+
[start.year, start.month, today.year, today.month]
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.render(dat, params)
|
62
|
+
case params[:output]
|
63
|
+
when 'json'
|
64
|
+
puts JSON.dump(dat)
|
65
|
+
when 'nu'
|
66
|
+
LucaSupport::View.nushell(YAML.dump(dat))
|
67
|
+
else
|
68
|
+
puts YAML.dump(dat)
|
42
69
|
end
|
43
70
|
end
|
44
71
|
end
|
@@ -57,7 +84,7 @@ when /journals?/, 'j'
|
|
57
84
|
case subcmd
|
58
85
|
when 'import'
|
59
86
|
OptionParser.new do |opt|
|
60
|
-
opt.banner = 'Usage: luca-book journals import filepath'
|
87
|
+
opt.banner = 'Usage: luca-book journals import [options] filepath'
|
61
88
|
opt.on('-c', '--config VAL', 'import definition'){ |v| params['config'] = v }
|
62
89
|
opt.on('-j', '--json', 'import via json format'){ |_v| params['json'] = true }
|
63
90
|
args = opt.parse!(ARGV)
|
@@ -65,23 +92,37 @@ when /journals?/, 'j'
|
|
65
92
|
end
|
66
93
|
when 'list'
|
67
94
|
OptionParser.new do |opt|
|
68
|
-
opt.banner = 'Usage: luca-book journals list [
|
95
|
+
opt.banner = 'Usage: luca-book journals list [options] [YYYY M]'
|
69
96
|
opt.on('-c', '--code VAL', 'search with code') { |v| params['code'] = v }
|
97
|
+
opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
|
98
|
+
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
99
|
+
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
70
100
|
opt.on_tail('List records. If you specify code and/or month, search on each criteria.')
|
71
101
|
args = opt.parse!(ARGV)
|
72
102
|
LucaCmd::Journal.list(args, params)
|
73
103
|
end
|
74
104
|
when 'stats'
|
75
105
|
OptionParser.new do |opt|
|
76
|
-
opt.banner = 'Usage: luca-book
|
77
|
-
opt.on('-
|
106
|
+
opt.banner = 'Usage: luca-book journals stats [options] [YYYY M]'
|
107
|
+
opt.on('-c', '--code VAL', 'search with code') { |v| params['code'] = v }
|
108
|
+
opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
|
109
|
+
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
110
|
+
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
78
111
|
args = opt.parse!(ARGV)
|
79
112
|
LucaCmd::Journal.stats(args, params)
|
80
113
|
end
|
114
|
+
else
|
115
|
+
puts 'Proper subcommand needed.'
|
116
|
+
puts
|
117
|
+
puts 'Usage: luca-book (j|journal[s]) subcommand [options] [YYYY M YYYY M]'
|
118
|
+
puts ' import: import journals from JSON/TSV'
|
119
|
+
puts ' list: list journals'
|
120
|
+
puts ' stats: list account statistics'
|
121
|
+
exit 1
|
81
122
|
end
|
82
123
|
when 'new'
|
83
124
|
OptionParser.new do |opt|
|
84
|
-
opt.banner = 'Usage: luca-book new Dir'
|
125
|
+
opt.banner = 'Usage: luca-book new [options] Dir'
|
85
126
|
opt.on('-c', '--country VAL', 'specify country code') { |v| params['coountry'] = v }
|
86
127
|
args = opt.parse(ARGV)
|
87
128
|
new_pj(args, params)
|
@@ -91,23 +132,37 @@ when /reports?/, 'r'
|
|
91
132
|
case subcmd
|
92
133
|
when 'bs'
|
93
134
|
OptionParser.new do |opt|
|
94
|
-
opt.banner = 'Usage: luca-book reports bs'
|
135
|
+
opt.banner = 'Usage: luca-book reports bs [options] [YYYY M]'
|
95
136
|
opt.on('-l', '--level VAL', 'account level') { |v| params[:level] = v.to_i }
|
96
137
|
opt.on('--legal', 'show legal mandatory account') { |_v| params[:legal] = true }
|
138
|
+
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
139
|
+
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
97
140
|
args = opt.parse!(ARGV)
|
98
141
|
LucaCmd::Report.balancesheet(args, params)
|
99
142
|
end
|
100
143
|
when 'pl'
|
101
144
|
OptionParser.new do |opt|
|
102
|
-
opt.banner = 'Usage: luca-book reports pl'
|
145
|
+
opt.banner = 'Usage: luca-book reports pl [options] [YYYY M YYYY M]'
|
146
|
+
opt.on('-l', '--level VAL', 'account level') { |v| params[:level] = v.to_i }
|
147
|
+
opt.on('-n VAL', 'report count') { |v| params[:n] = v.to_i }
|
148
|
+
opt.on('--nu', 'show table in nushell') { |_v| params[:output] = 'nu' }
|
149
|
+
opt.on('-o', '--output VAL', 'output serialized data') { |v| params[:output] = v }
|
103
150
|
args = opt.parse!(ARGV)
|
104
151
|
LucaCmd::Report.profitloss(args, params)
|
105
152
|
end
|
153
|
+
else
|
154
|
+
puts 'Proper subcommand needed.'
|
155
|
+
puts
|
156
|
+
puts 'Usage: luca-book (r|report[s]) (bs|pl) [options] YYYY M'
|
157
|
+
puts ' bs: show balance sheet'
|
158
|
+
puts ' pl: show statement of income'
|
159
|
+
exit 1
|
106
160
|
end
|
107
|
-
|
108
|
-
puts '
|
161
|
+
else
|
162
|
+
puts 'Proper subcommand needed.'
|
163
|
+
puts
|
164
|
+
puts 'Usage: luca-book (j[ournals]|r[eports]) subcommand'
|
109
165
|
puts ' journals: operate journal records'
|
110
166
|
puts ' reports: show reports'
|
111
|
-
|
112
|
-
puts 'Invalid subcommand'
|
167
|
+
exit 1
|
113
168
|
end
|
data/lib/luca_book/dict.rb
CHANGED
@@ -7,6 +7,83 @@ require 'pathname'
|
|
7
7
|
|
8
8
|
module LucaBook
|
9
9
|
class Dict < LucaRecord::Dict
|
10
|
+
# Column number settings for CSV/TSV convert
|
11
|
+
#
|
12
|
+
# :label
|
13
|
+
# for double entry data
|
14
|
+
# :counter_label
|
15
|
+
# must be specified with label
|
16
|
+
# :debit_label
|
17
|
+
# for double entry data
|
18
|
+
# * debit_value
|
19
|
+
# :credit_label
|
20
|
+
# for double entry data
|
21
|
+
# * credit_value
|
22
|
+
# :note
|
23
|
+
# can be the same column as another label
|
24
|
+
#
|
25
|
+
# :encoding
|
26
|
+
# file encoding
|
27
|
+
#
|
28
|
+
def csv_config
|
29
|
+
{}.tap do |config|
|
30
|
+
if @config.dig('label')
|
31
|
+
config[:label] = @config['label'].to_i
|
32
|
+
if @config.dig('counter_label')
|
33
|
+
config[:counter_label] = @config['counter_label']
|
34
|
+
config[:type] = 'single'
|
35
|
+
end
|
36
|
+
elsif @config.dig('debit_label')
|
37
|
+
config[:debit_label] = @config['debit_label'].to_i
|
38
|
+
if @config.dig('credit_label')
|
39
|
+
config[:credit_label] = @config['credit_label'].to_i
|
40
|
+
config[:type] = 'double'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
config[:type] ||= 'invalid'
|
44
|
+
config[:debit_value] = @config['debit_value'].to_i if @config.dig('debit_value')
|
45
|
+
config[:credit_value] = @config['credit_value'].to_i if @config.dig('credit_value')
|
46
|
+
config[:note] = @config['note'] if @config.dig('note')
|
47
|
+
config[:encoding] = @config['encoding'] if @config.dig('encoding')
|
48
|
+
|
49
|
+
config[:year] = @config['year'] if @config.dig('year')
|
50
|
+
config[:month] = @config['month'] if @config.dig('month')
|
51
|
+
config[:day] = @config['day'] if @config.dig('day')
|
52
|
+
config[:default_debit] = @config['default_debit'] if @config.dig('default_debit')
|
53
|
+
config[:default_credit] = @config['default_credit'] if @config.dig('default_credit')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def search(word, default_word = nil, amount = nil)
|
58
|
+
res = super(word, default_word, main_key: 'account_label')
|
59
|
+
if res.is_a?(Array) && res[0].is_a?(Array)
|
60
|
+
filter_amount(res, amount)
|
61
|
+
else
|
62
|
+
res
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Choose setting on Big or small condition.
|
67
|
+
#
|
68
|
+
def filter_amount(settings, amount = nil)
|
69
|
+
return settings[0] if amount.nil?
|
70
|
+
|
71
|
+
settings.each do |item|
|
72
|
+
return item unless item[1].keys.include?(:on_amount)
|
73
|
+
|
74
|
+
condition = item.dig(1, :on_amount)
|
75
|
+
case condition[0]
|
76
|
+
when '>'
|
77
|
+
return item if amount > BigDecimal(condition[1..])
|
78
|
+
when '<'
|
79
|
+
return item if amount < BigDecimal(condition[1..])
|
80
|
+
else
|
81
|
+
return item
|
82
|
+
end
|
83
|
+
end
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
10
87
|
def self.latest_balance
|
11
88
|
dict_dir = Pathname(LucaSupport::Config::Pjdir) / 'data' / 'balance'
|
12
89
|
# TODO: search latest balance dictionary
|
data/lib/luca_book/import.rb
CHANGED
@@ -4,9 +4,14 @@ require 'date'
|
|
4
4
|
require 'json'
|
5
5
|
require 'luca_book'
|
6
6
|
require 'luca_support'
|
7
|
-
#require 'luca_book/dict'
|
8
7
|
require 'luca_record'
|
9
8
|
|
9
|
+
begin
|
10
|
+
require "luca_book/import_#{LucaSupport::CONFIG['country']}"
|
11
|
+
rescue LoadError => e
|
12
|
+
e.message
|
13
|
+
end
|
14
|
+
|
10
15
|
module LucaBook
|
11
16
|
class Import
|
12
17
|
DEBIT_DEFAULT = '10XX'
|
@@ -18,7 +23,7 @@ module LucaBook
|
|
18
23
|
@target_file = path
|
19
24
|
# TODO: yaml need to be configurable
|
20
25
|
@dict_name = dict
|
21
|
-
@dict =
|
26
|
+
@dict = LucaBook::Dict.new("import-#{dict}.yaml")
|
22
27
|
@code_map = LucaRecord::Dict.reverse(LucaRecord::Dict.load('base.tsv'))
|
23
28
|
@config = @dict.csv_config if dict
|
24
29
|
end
|
@@ -45,8 +50,6 @@ module LucaBook
|
|
45
50
|
#
|
46
51
|
def self.import_json(io)
|
47
52
|
JSON.parse(io).each do |d|
|
48
|
-
validate(d)
|
49
|
-
|
50
53
|
code_map = LucaRecord::Dict.reverse(LucaRecord::Dict.load('base.tsv'))
|
51
54
|
d['debit'].each { |h| h['code'] = code_map.dig(h['label']) || DEBIT_DEFAULT }
|
52
55
|
d['credit'].each { |h| h['code'] = code_map.dig(h['label']) || CREDIT_DEFAULT }
|
@@ -67,46 +70,39 @@ module LucaBook
|
|
67
70
|
end
|
68
71
|
end
|
69
72
|
|
70
|
-
def self.validate(obj)
|
71
|
-
raise 'NoDateKey' unless obj.key?('date')
|
72
|
-
raise 'NoDebitKey' unless obj.key?('debit')
|
73
|
-
raise 'NoDebitValue' if obj['debit'].empty?
|
74
|
-
raise 'NoCreditKey' unless obj.key?('credit')
|
75
|
-
raise 'NoCreditValue' if obj['credit'].empty?
|
76
|
-
end
|
77
|
-
|
78
73
|
private
|
79
74
|
|
80
|
-
#
|
81
75
|
# convert single entry data
|
82
76
|
#
|
83
77
|
def parse_single(row)
|
84
|
-
|
78
|
+
if (row.dig(@config[:credit_value]) || []).empty?
|
79
|
+
value = BigDecimal(row[@config[:debit_value]])
|
80
|
+
debit = true
|
81
|
+
else
|
82
|
+
value = BigDecimal(row[@config[:credit_value]])
|
83
|
+
end
|
84
|
+
default_label = debit ? @config.dig(:default_debit) : @config.dig(:default_credit)
|
85
|
+
code, options = search_code(row[@config[:label]], default_label, value)
|
86
|
+
counter_code = @code_map.dig(@config[:counter_label])
|
87
|
+
if respond_to? :tax_extension
|
88
|
+
data, data_c = tax_extension(code, counter_code, value, options) if options
|
89
|
+
end
|
90
|
+
data ||= [{ 'code' => code, 'value' => value }]
|
91
|
+
data_c ||= [{ 'code' => counter_code, 'value' => value }]
|
85
92
|
{}.tap do |d|
|
86
93
|
d['date'] = parse_date(row)
|
87
|
-
if
|
88
|
-
d['debit'] =
|
89
|
-
|
90
|
-
]
|
91
|
-
d['credit'] = [
|
92
|
-
{ 'code' => @code_map.dig(@config[:counter_label]) }
|
93
|
-
]
|
94
|
+
if debit
|
95
|
+
d['debit'] = data
|
96
|
+
d['credit'] = data_c
|
94
97
|
else
|
95
|
-
d['debit'] =
|
96
|
-
|
97
|
-
]
|
98
|
-
d['credit'] = [
|
99
|
-
{ 'code' => search_code(row[@config[:label]], @config.dig(:default_credit)) || CREDIT_DEFAULT }
|
100
|
-
]
|
98
|
+
d['debit'] = data_c
|
99
|
+
d['credit'] = data
|
101
100
|
end
|
102
|
-
d['debit'][0]['value'] = value
|
103
|
-
d['credit'][0]['value'] = value
|
104
101
|
d['note'] = Array(@config[:note]).map{ |col| row[col] }.join(' ')
|
105
102
|
d['x-editor'] = "LucaBook::Import/#{@dict_name}"
|
106
103
|
end
|
107
104
|
end
|
108
105
|
|
109
|
-
#
|
110
106
|
# convert double entry data
|
111
107
|
#
|
112
108
|
def parse_double(row)
|
@@ -125,8 +121,9 @@ module LucaBook
|
|
125
121
|
end
|
126
122
|
end
|
127
123
|
|
128
|
-
def search_code(label, default_label)
|
129
|
-
@
|
124
|
+
def search_code(label, default_label, amount = nil)
|
125
|
+
label, options = @dict.search(label, default_label, amount)
|
126
|
+
[@code_map.dig(label), options]
|
130
127
|
end
|
131
128
|
|
132
129
|
def parse_date(row)
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'date'
|
4
|
+
require 'luca_book'
|
5
|
+
require 'luca_support'
|
6
|
+
|
7
|
+
module LucaBook
|
8
|
+
class Import
|
9
|
+
# TODO: need to be separated into pluggable l10n module.
|
10
|
+
# TODO: gensen rate >1m yen.
|
11
|
+
# TODO: gensen & consumption `round()` rules need to be confirmed.
|
12
|
+
# Profit or Loss account should be specified as code1.
|
13
|
+
#
|
14
|
+
def tax_extension(code1, code2, amount, options)
|
15
|
+
return nil if options.nil? || options[:tax_options].nil?
|
16
|
+
return nil if !options[:tax_options].include?('jp-gensen') && !options[:tax_options].include?('jp-consumption')
|
17
|
+
|
18
|
+
gensen_rate = BigDecimal('0.1021')
|
19
|
+
consumption_rate = BigDecimal('0.1')
|
20
|
+
gensen_code = @code_map.dig(options[:gensen_label]) || @code_map.dig('預り金')
|
21
|
+
gensen_idx = /^[5-8B-G]/.match(code1) ? 1 : 0
|
22
|
+
consumption_idx = /^[A-G]/.match(code1) ? 0 : 1
|
23
|
+
consumption_code = @code_map.dig(options[:consumption_label])
|
24
|
+
consumption_code ||= /^[A]/.match(code1) ? @code_map.dig('仮受消費税等') : @code_map.dig('仮払消費税等')
|
25
|
+
if options[:tax_options].include?('jp-gensen') && options[:tax_options].include?('jp-consumption')
|
26
|
+
paid_rate = BigDecimal('1') + consumption_rate - gensen_rate
|
27
|
+
gensen_amount = (amount / paid_rate * gensen_rate).round
|
28
|
+
consumption_amount = (amount / paid_rate * consumption_rate).round
|
29
|
+
[].tap do |res|
|
30
|
+
res << [].tap do |res1|
|
31
|
+
amount1 = amount
|
32
|
+
amount1 -= consumption_amount if consumption_idx == 0
|
33
|
+
amount1 += gensen_amount if gensen_idx == 1
|
34
|
+
res1 << { 'code' => code1, 'value' => amount1 }
|
35
|
+
res1 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 0
|
36
|
+
res1 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 0
|
37
|
+
end
|
38
|
+
res << [].tap do |res2|
|
39
|
+
amount2 = amount
|
40
|
+
amount2 -= consumption_amount if consumption_idx == 1
|
41
|
+
amount2 += gensen_amount if gensen_idx == 0
|
42
|
+
res2 << { 'code' => code2, 'value' => amount2 }
|
43
|
+
res2 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 1
|
44
|
+
res2 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
elsif options[:tax_options].include?('jp-gensen')
|
48
|
+
paid_rate = BigDecimal('1') - gensen_rate
|
49
|
+
gensen_amount = (amount / paid_rate * gensen_rate).round
|
50
|
+
[].tap do |res|
|
51
|
+
res << [].tap do |res1|
|
52
|
+
amount1 = amount
|
53
|
+
amount1 += gensen_amount if gensen_idx == 1
|
54
|
+
res1 << { 'code' => code, 'value' => amount1 }
|
55
|
+
res1 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 0
|
56
|
+
end
|
57
|
+
res << [].tap do |res2|
|
58
|
+
amount2 = amount
|
59
|
+
amount2 += gensen_amount if gensen_idx == 0
|
60
|
+
mount2 ||= amount
|
61
|
+
res2 << { 'code' => code2, 'value' => amount2 }
|
62
|
+
res2 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
elsif options[:tax_options].include?('jp-consumption')
|
66
|
+
paid_rate = BigDecimal('1') + consumption_rate - gensen_rate
|
67
|
+
consumption_amount = (amount / paid_rate * consumption_rate).round
|
68
|
+
res << [].tap do |res1|
|
69
|
+
amount1 = amount
|
70
|
+
amount1 -= consumption_amount if consumption_idx == 0
|
71
|
+
res1 << { 'code' => code1, 'value' => amount1 }
|
72
|
+
res1 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 0
|
73
|
+
end
|
74
|
+
res << [].tap do |res2|
|
75
|
+
amount2 = amount
|
76
|
+
amount2 -= consumption_amount if consumption_idx == 1
|
77
|
+
res2 << { 'code' => code2, 'value' => amount2 }
|
78
|
+
res2 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/luca_book/journal.rb
CHANGED
@@ -13,6 +13,7 @@ module LucaBook
|
|
13
13
|
# create journal from hash
|
14
14
|
#
|
15
15
|
def self.create(d)
|
16
|
+
validate(d)
|
16
17
|
date = Date.parse(d['date'])
|
17
18
|
|
18
19
|
debit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['debit'], 'value'))
|
@@ -52,6 +53,22 @@ module LucaBook
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
56
|
+
def self.validate(obj)
|
57
|
+
raise 'NoDateKey' unless obj.key?('date')
|
58
|
+
raise 'NoDebitKey' unless obj.key?('debit')
|
59
|
+
raise 'NoCreditKey' unless obj.key?('credit')
|
60
|
+
debit_codes = serialize_on_key(obj['debit'], 'code').compact
|
61
|
+
debit_values = serialize_on_key(obj['debit'], 'value').compact
|
62
|
+
raise 'NoDebitCode' if debit_codes.empty?
|
63
|
+
raise 'NoDebitValue' if debit_values.empty?
|
64
|
+
raise 'UnmatchDebit' if debit_codes.length != debit_values.length
|
65
|
+
credit_codes = serialize_on_key(obj['credit'], 'code').compact
|
66
|
+
credit_values = serialize_on_key(obj['credit'], 'value').compact
|
67
|
+
raise 'NoCreditCode' if credit_codes.empty?
|
68
|
+
raise 'NoCreditValue' if credit_values.empty?
|
69
|
+
raise 'UnmatchCredit' if credit_codes.length != credit_values.length
|
70
|
+
end
|
71
|
+
|
55
72
|
# collect values on specified key
|
56
73
|
#
|
57
74
|
def self.serialize_on_key(array_of_hash, key)
|
data/lib/luca_book/list.rb
CHANGED
@@ -47,7 +47,7 @@ module LucaBook
|
|
47
47
|
res['note'] = dat[:note]
|
48
48
|
end
|
49
49
|
end
|
50
|
-
|
50
|
+
readable(@data)
|
51
51
|
end
|
52
52
|
|
53
53
|
def list_journals
|
@@ -65,7 +65,7 @@ module LucaBook
|
|
65
65
|
res['note'] = dat[:note]
|
66
66
|
end
|
67
67
|
end
|
68
|
-
|
68
|
+
readable(@data)
|
69
69
|
end
|
70
70
|
|
71
71
|
def accumulate_code
|
@@ -74,10 +74,6 @@ module LucaBook
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
def to_yaml
|
78
|
-
YAML.dump(LucaSupport::Code.readable(@data)).tap { |data| puts data }
|
79
|
-
end
|
80
|
-
|
81
77
|
private
|
82
78
|
|
83
79
|
def set_balance
|
data/lib/luca_book/state.rb
CHANGED
@@ -17,28 +17,15 @@ module LucaBook
|
|
17
17
|
|
18
18
|
attr_reader :statement
|
19
19
|
|
20
|
-
def initialize(data, count = nil)
|
20
|
+
def initialize(data, count = nil, date: nil)
|
21
21
|
@data = data
|
22
22
|
@count = count
|
23
23
|
@dict = LucaRecord::Dict.load('base.tsv')
|
24
|
+
@start_date = date
|
24
25
|
@start_balance = set_balance
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
-
def search_tag(code)
|
29
|
-
count = 0
|
30
|
-
Dir.children(LucaSupport::Config::Pjdir).sort.each do |dir|
|
31
|
-
next if ! FileTest.directory?(LucaSupport::Config::Pjdir+dir)
|
32
|
-
|
33
|
-
open_records(datadir, dir, 3) do |row, i|
|
34
|
-
next if i == 2
|
35
|
-
count += 1 if row.include?(code)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
puts "#{code}: #{count}"
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.term(from_year, from_month, to_year = from_year, to_month = from_month)
|
28
|
+
def self.range(from_year, from_month, to_year = from_year, to_month = from_month)
|
42
29
|
date = Date.new(from_year.to_i, from_month.to_i, -1)
|
43
30
|
last_date = Date.new(to_year.to_i, to_month.to_i, -1)
|
44
31
|
raise 'invalid term specified' if date > last_date
|
@@ -47,56 +34,57 @@ module LucaBook
|
|
47
34
|
reports = [].tap do |r|
|
48
35
|
while date <= last_date do
|
49
36
|
diff, count = accumulate_month(date.year, date.month)
|
50
|
-
r << diff
|
51
|
-
counts << count
|
52
|
-
date = date.next_month
|
37
|
+
r << diff.tap { |c| c['_d'] = date.to_s }
|
38
|
+
counts << count.tap { |c| c['_d'] = date.to_s }
|
39
|
+
date = Date.new(date.next_month.year, date.next_month.month, -1)
|
53
40
|
end
|
54
41
|
end
|
55
|
-
new
|
42
|
+
new(reports, counts, date: Date.new(from_year.to_i, from_month.to_i, -1))
|
56
43
|
end
|
57
44
|
|
58
|
-
def by_code(code,
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
full_term = self.class.scan_terms
|
63
|
-
if ! month.nil?
|
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)
|
67
|
-
else
|
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)
|
71
|
-
}.flatten.prepend(start)
|
72
|
-
end
|
73
|
-
end
|
45
|
+
def self.by_code(code, from_year, from_month, to_year = from_year, to_month = from_month)
|
46
|
+
date = Date.new(from_year.to_i, from_month.to_i, -1)
|
47
|
+
last_date = Date.new(to_year.to_i, to_month.to_i, -1)
|
48
|
+
raise 'invalid term specified' if date > last_date
|
74
49
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
50
|
+
reports = [].tap do |r|
|
51
|
+
while date <= last_date do
|
52
|
+
diff = {}.tap do |h|
|
53
|
+
g = gross(date.year, date.month, code: code)
|
54
|
+
sum = g.dig(:debit).nil? ? BigDecimal('0') : Util.calc_diff(g[:debit], code)
|
55
|
+
sum -= g.dig(:credit).nil? ? BigDecimal('0') : Util.calc_diff(g[:credit], code)
|
56
|
+
h['code'] = code
|
57
|
+
h['label'] = LucaRecord::Dict.load('base.tsv').dig(code, :label)
|
58
|
+
h['net'] = sum
|
59
|
+
h['debit_amount'] = g[:debit]
|
60
|
+
h['debit_count'] = g[:debit_count]
|
61
|
+
h['credit_amount'] = g[:credit]
|
62
|
+
h['credit_count'] = g[:credit_count]
|
63
|
+
h['_d'] = date.to_s
|
64
|
+
end
|
65
|
+
r << diff
|
66
|
+
date = Date.new(date.next_month.year, date.next_month.month, -1)
|
67
|
+
end
|
79
68
|
end
|
80
|
-
|
81
|
-
|
82
|
-
def to_yaml
|
83
|
-
YAML.dump(code2label).tap { |data| puts data }
|
69
|
+
LucaSupport::Code.readable(reports)
|
84
70
|
end
|
85
71
|
|
86
72
|
def code2label
|
87
73
|
@statement ||= @data
|
88
74
|
@statement.map do |report|
|
89
75
|
{}.tap do |h|
|
90
|
-
report.each { |k, v| h[@dict.dig(k, :label)] = v }
|
76
|
+
report.each { |k, v| h[@dict.dig(k, :label) || k] = v }
|
91
77
|
end
|
92
78
|
end
|
93
79
|
end
|
94
80
|
|
95
81
|
def stats(level = nil)
|
96
|
-
keys = @count.map(&:keys).flatten.uniq.sort
|
82
|
+
keys = @count.map(&:keys).flatten.push('_t').uniq.sort
|
97
83
|
@count.map! do |data|
|
84
|
+
sum = 0
|
98
85
|
keys.each do |k|
|
99
86
|
data[k] ||= 0
|
87
|
+
sum += data[k] if /^[^_]/.match(k)
|
100
88
|
next if level.nil? || k.length <= level
|
101
89
|
|
102
90
|
if data[k[0, level]]
|
@@ -106,34 +94,34 @@ module LucaBook
|
|
106
94
|
end
|
107
95
|
end
|
108
96
|
data.select! { |k, _v| k.length <= level } if level
|
97
|
+
data['_t'] = sum
|
109
98
|
data.sort.to_h
|
110
99
|
end
|
111
100
|
keys.map! { |k| k[0, level] }.uniq.select! { |k| k.length <= level } if level
|
112
101
|
@count.prepend({}.tap { |header| keys.each { |k| header[k] = @dict.dig(k, :label) }})
|
113
|
-
puts YAML.dump(@count)
|
114
102
|
@count
|
115
103
|
end
|
116
104
|
|
117
105
|
def bs(level = 3, legal: false)
|
106
|
+
@start_balance.keys.each { |k| @data.first[k] ||= 0 }
|
118
107
|
@data.map! { |data| data.select { |k, _v| k.length <= level } }
|
119
108
|
@data.map! { |data| code_sum(data).merge(data) } if legal
|
120
109
|
base = accumulate_balance(@data)
|
121
|
-
|
110
|
+
rows = [base[:debit].length, base[:credit].length].max
|
122
111
|
@statement = [].tap do |a|
|
123
|
-
|
112
|
+
rows.times do |i|
|
124
113
|
{}.tap do |res|
|
125
114
|
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] : ''
|
115
|
+
res['debit_balance'] = base[:debit][i] ? (@start_balance.dig(base[:debit][i].keys[0]) || 0) + base[:debit][i].values[0] : ''
|
127
116
|
res['debit_diff'] = base[:debit][i] ? base[:debit][i].values[0] : ''
|
128
117
|
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] : ''
|
118
|
+
res['credit_balance'] = base[:credit][i] ? (@start_balance.dig(base[:credit][i].keys[0]) || 0) + base[:credit][i].values[0] : ''
|
130
119
|
res['credit_diff'] = base[:credit][i] ? base[:credit][i].values[0] : ''
|
131
120
|
a << res
|
132
121
|
end
|
133
122
|
end
|
134
123
|
end
|
135
|
-
|
136
|
-
self
|
124
|
+
readable(@statement)
|
137
125
|
end
|
138
126
|
|
139
127
|
def accumulate_balance(monthly_diffs)
|
@@ -141,23 +129,58 @@ module LucaBook
|
|
141
129
|
month.each do |k, v|
|
142
130
|
h[k] = h[k].nil? ? v : h[k] + v
|
143
131
|
end
|
144
|
-
end
|
132
|
+
end
|
145
133
|
{ debit: [], credit: [] }.tap do |res|
|
146
|
-
data.each do |k, v|
|
134
|
+
data.sort.to_h.each do |k, v|
|
147
135
|
case k
|
148
136
|
when /^[0-4].*/
|
149
137
|
res[:debit] << { k => v }
|
150
|
-
when /^[5-
|
138
|
+
when /^[5-9].*/
|
151
139
|
res[:credit] << { k => v }
|
152
140
|
end
|
153
141
|
end
|
154
142
|
end
|
155
143
|
end
|
156
144
|
|
157
|
-
def pl
|
158
|
-
|
159
|
-
|
160
|
-
|
145
|
+
def pl(level = 2)
|
146
|
+
term_keys = @data.inject([]) { |a, data| a + data.keys }
|
147
|
+
.compact.select { |k| /^[A-H_].+/.match(k) }
|
148
|
+
fy = @start_balance.select { |k, _v| /^[A-H].+/.match(k) }
|
149
|
+
keys = (term_keys + fy.keys).uniq.sort
|
150
|
+
keys.select! { |k| k.length <= level }
|
151
|
+
@statement = @data.map do |data|
|
152
|
+
{}.tap do |h|
|
153
|
+
keys.each { |k| h[k] = data[k] || BigDecimal('0') }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
term = @statement.each_with_object({}) do |item, h|
|
157
|
+
item.each do |k, v|
|
158
|
+
h[k] = h[k].nil? ? v : h[k] + v if /^[^_]/.match(k)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
fy = {}.tap do |h|
|
162
|
+
keys.each do |k|
|
163
|
+
h[k] = BigDecimal(fy[k] || '0') + BigDecimal(term[k] || '0')
|
164
|
+
end
|
165
|
+
end
|
166
|
+
@statement << term.tap { |h| h['_d'] = 'Period Total' }
|
167
|
+
@statement << fy.tap { |h| h['_d'] = 'FY Total' }
|
168
|
+
readable(code2label)
|
169
|
+
end
|
170
|
+
|
171
|
+
def self.accumulate_term(start_year, start_month, end_year, end_month)
|
172
|
+
date = Date.new(start_year, start_month, 1)
|
173
|
+
last_date = Date.new(end_year, end_month, -1)
|
174
|
+
return nil if date > last_date
|
175
|
+
|
176
|
+
{}.tap do |res|
|
177
|
+
diff, _count = net(date.year, date.month, last_date.year, last_date.month)
|
178
|
+
diff.each do |k, v|
|
179
|
+
next if /^[_]/.match(k)
|
180
|
+
|
181
|
+
res[k] = res[k].nil? ? v : res[k] + v
|
182
|
+
end
|
183
|
+
end
|
161
184
|
end
|
162
185
|
|
163
186
|
def self.accumulate_month(year, month)
|
@@ -169,12 +192,6 @@ module LucaBook
|
|
169
192
|
#
|
170
193
|
def self.total_subaccount(report)
|
171
194
|
{}.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
195
|
res['A0'] = sum_matched(report, /^[A][0-9A-Z]{2,}/)
|
179
196
|
res['B0'] = sum_matched(report, /^[B][0-9A-Z]{2,}/)
|
180
197
|
res['BA'] = res['A0'] - res['B0']
|
@@ -184,12 +201,28 @@ module LucaBook
|
|
184
201
|
res['E0'] = sum_matched(report, /^[E][0-9A-Z]{2,}/)
|
185
202
|
res['EA'] = res['CA'] + res['D0'] - res['E0']
|
186
203
|
res['F0'] = sum_matched(report, /^[F][0-9A-Z]{2,}/)
|
187
|
-
res['G0'] = sum_matched(report, /^[G][0-9A-Z]{
|
204
|
+
res['G0'] = sum_matched(report, /^[G][0-9][0-9A-Z]{1,}/)
|
188
205
|
res['GA'] = res['EA'] + res['F0'] - res['G0']
|
189
|
-
res['
|
206
|
+
res['H0'] = sum_matched(report, /^[H][0-9][0-9A-Z]{1,}/)
|
207
|
+
res['HA'] = res['GA'] - res['H0']
|
208
|
+
|
209
|
+
report['9142'] = (report['9142'] || BigDecimal('0')) + res['HA']
|
210
|
+
res['9142'] = report['9142']
|
211
|
+
res['10'] = sum_matched(report, /^[123][0-9A-Z]{2,}/)
|
212
|
+
res['40'] = sum_matched(report, /^[4][0-9A-Z]{2,}/)
|
213
|
+
res['50'] = sum_matched(report, /^[56][0-9A-Z]{2,}/)
|
214
|
+
res['70'] = sum_matched(report, /^[78][0-9A-Z]{2,}/)
|
215
|
+
res['91'] = sum_matched(report, /^91[0-9A-Z]{1,}/)
|
216
|
+
res['8ZZ'] = res['50'] + res['70']
|
217
|
+
res['9ZZ'] = sum_matched(report, /^[9][0-9A-Z]{2,}/)
|
190
218
|
|
191
219
|
res['1'] = res['10'] + res['40']
|
192
|
-
res['5'] = res['8ZZ'] + res['9ZZ']
|
220
|
+
res['5'] = res['8ZZ'] + res['9ZZ']
|
221
|
+
res['_d'] = report['_d']
|
222
|
+
|
223
|
+
report.each do |k, v|
|
224
|
+
res[k] = v if k.length == 3
|
225
|
+
end
|
193
226
|
|
194
227
|
report.each do |k, v|
|
195
228
|
if k.length >= 4
|
@@ -211,10 +244,23 @@ module LucaBook
|
|
211
244
|
end
|
212
245
|
|
213
246
|
def set_balance
|
247
|
+
pre_last = @start_date.prev_month
|
248
|
+
pre = if @start_date.month > LucaSupport::CONFIG['fy_start'].to_i
|
249
|
+
self.class.accumulate_term(pre_last.year, LucaSupport::CONFIG['fy_start'], pre_last.year, pre_last.month)
|
250
|
+
elsif @start_date.month < LucaSupport::CONFIG['fy_start'].to_i
|
251
|
+
self.class.accumulate_term(pre_last.year - 1, LucaSupport::CONFIG['fy_start'], pre_last.year, pre_last.month)
|
252
|
+
end
|
253
|
+
|
214
254
|
base = Dict.latest_balance.each_with_object({}) do |(k, v), h|
|
215
|
-
h[k] = v[:balance].
|
255
|
+
h[k] = BigDecimal(v[:balance].to_s) if v[:balance]
|
256
|
+
end
|
257
|
+
if pre
|
258
|
+
idx = (pre.keys + base.keys).uniq
|
259
|
+
base = {}.tap do |h|
|
260
|
+
idx.each { |k| h[k] = (base[k] || BigDecimal('0')) + (pre[k] || BigDecimal('0')) }
|
261
|
+
end
|
216
262
|
end
|
217
|
-
|
263
|
+
self.class.total_subaccount(base)
|
218
264
|
end
|
219
265
|
|
220
266
|
def self.sum_matched(report, reg)
|
@@ -222,39 +268,49 @@ module LucaBook
|
|
222
268
|
end
|
223
269
|
|
224
270
|
# for assert purpose
|
225
|
-
|
271
|
+
#
|
272
|
+
def self.gross(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil, rows: 4)
|
226
273
|
if ! date_range.nil?
|
227
274
|
raise if date_range.class != Range
|
228
275
|
# TODO: date based range search
|
229
276
|
end
|
230
277
|
|
278
|
+
end_year ||= start_year
|
279
|
+
end_month ||= start_month
|
231
280
|
sum = { debit: {}, credit: {}, debit_count: {}, credit_count: {} }
|
232
281
|
idx_memo = []
|
233
|
-
|
282
|
+
term(start_year, start_month, end_year, end_month, code) do |f, _path|
|
234
283
|
CSV.new(f, headers: false, col_sep: "\t", encoding: 'UTF-8')
|
235
284
|
.each_with_index do |row, i|
|
236
285
|
break if i >= rows
|
286
|
+
|
237
287
|
case i
|
238
288
|
when 0
|
239
289
|
idx_memo = row.map(&:to_s)
|
290
|
+
next if code && !idx_memo.include?(code)
|
291
|
+
|
240
292
|
idx_memo.each do |r|
|
241
|
-
sum[:debit][r] ||= 0
|
293
|
+
sum[:debit][r] ||= BigDecimal('0')
|
242
294
|
sum[:debit_count][r] ||= 0
|
243
295
|
end
|
244
296
|
when 1
|
297
|
+
next if code && !idx_memo.include?(code)
|
298
|
+
|
245
299
|
row.each_with_index do |r, j|
|
246
|
-
sum[:debit][idx_memo[j]] += r.
|
300
|
+
sum[:debit][idx_memo[j]] += BigDecimal(r.to_s)
|
247
301
|
sum[:debit_count][idx_memo[j]] += 1
|
248
302
|
end
|
249
303
|
when 2
|
250
304
|
idx_memo = row.map(&:to_s)
|
305
|
+
break if code && !idx_memo.include?(code)
|
306
|
+
|
251
307
|
idx_memo.each do |r|
|
252
|
-
sum[:credit][r] ||= 0
|
308
|
+
sum[:credit][r] ||= BigDecimal('0')
|
253
309
|
sum[:credit_count][r] ||= 0
|
254
310
|
end
|
255
311
|
when 3
|
256
312
|
row.each_with_index do |r, j|
|
257
|
-
sum[:credit][idx_memo[j]] += r.
|
313
|
+
sum[:credit][idx_memo[j]] += BigDecimal(r.to_s)
|
258
314
|
sum[:credit_count][idx_memo[j]] += 1
|
259
315
|
end
|
260
316
|
else
|
@@ -262,41 +318,31 @@ module LucaBook
|
|
262
318
|
end
|
263
319
|
end
|
264
320
|
end
|
321
|
+
if code
|
322
|
+
sum[:debit] = sum[:debit][code] || BigDecimal('0')
|
323
|
+
sum[:credit] = sum[:credit][code] || BigDecimal('0')
|
324
|
+
sum[:debit_count] = sum[:debit_count][code] || 0
|
325
|
+
sum[:credit_count] = sum[:credit_count][code] || 0
|
326
|
+
end
|
265
327
|
sum
|
266
328
|
end
|
267
329
|
|
268
330
|
# netting vouchers in specified term
|
269
|
-
|
270
|
-
|
331
|
+
#
|
332
|
+
def self.net(start_year, start_month, end_year = nil, end_month = nil, code: nil, date_range: nil)
|
333
|
+
g = gross(start_year, start_month, end_year, end_month, code: code, date_range: date_range)
|
271
334
|
idx = (g[:debit].keys + g[:credit].keys).uniq.sort
|
272
335
|
count = {}
|
273
336
|
diff = {}.tap do |sum|
|
274
337
|
idx.each do |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)
|
338
|
+
sum[code] = g.dig(:debit, code).nil? ? BigDecimal('0') : Util.calc_diff(g[:debit][code], code)
|
339
|
+
sum[code] -= g.dig(:credit, code).nil? ? BigDecimal('0') : Util.calc_diff(g[:credit][code], code)
|
277
340
|
count[code] = (g.dig(:debit_count, code) || 0) + (g.dig(:credit_count, code) || 0)
|
278
341
|
end
|
279
342
|
end
|
280
343
|
[diff, count]
|
281
344
|
end
|
282
345
|
|
283
|
-
# TODO: replace load_tsv -> generic load_tsv_dict
|
284
|
-
def load_start
|
285
|
-
file = Pathname(LucaSupport::Config::Pjdir) / 'data' / 'balance' / 'start.tsv'
|
286
|
-
{}.tap do |dic|
|
287
|
-
load_tsv(file) do |row|
|
288
|
-
dic[row[0]] = row[2].to_i if ! row[2].nil?
|
289
|
-
end
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
def load_tsv(path)
|
294
|
-
return enum_for(:load_tsv, path) unless block_given?
|
295
|
-
|
296
|
-
data = CSV.read(path, headers: true, col_sep: "\t", encoding: 'UTF-8')
|
297
|
-
data.each { |row| yield row }
|
298
|
-
end
|
299
|
-
|
300
346
|
private
|
301
347
|
|
302
348
|
def legal_items
|
@@ -1,19 +1,19 @@
|
|
1
|
-
code label
|
1
|
+
code label xbrl_id consumption_tax income_tax
|
2
2
|
10 Current Assets
|
3
3
|
10XX UNSETTLED_IMPORT
|
4
4
|
110 Cash and cash equivalents
|
5
5
|
1101 Saving accounts
|
6
6
|
1102 Checking accounts
|
7
|
-
111 Cash
|
8
|
-
120 Notes receivable
|
9
|
-
130 Accounts receivable - trade
|
7
|
+
111 Cash us-gaap:Cash
|
8
|
+
120 Notes receivable us-gaap:NotesReceivableGross
|
9
|
+
130 Accounts receivable - trade us-gaap:AccountsReceivableGross
|
10
10
|
140 短期貸付金
|
11
11
|
150 未収入金
|
12
|
-
160 Inventory
|
12
|
+
160 Inventory us-gaap:InventoryGross
|
13
13
|
161 商品
|
14
14
|
162 製品
|
15
|
-
163 Inventory work in process
|
16
|
-
164 Supplies
|
15
|
+
163 Inventory work in process us-gaap:InventoryWorkInProcess
|
16
|
+
164 Supplies us-gaap:Supplies
|
17
17
|
180 その他流動資産
|
18
18
|
181 前渡金
|
19
19
|
182 Prepaid expenses
|
@@ -22,17 +22,17 @@ code label xbrl_id consumption_tax income_tax
|
|
22
22
|
1D0 Deferred income tax
|
23
23
|
40 Fixed Assets
|
24
24
|
410 Tangible Assets
|
25
|
-
411 Buildings
|
25
|
+
411 Buildings us-gaap:BuildingsAndImprovementsGross
|
26
26
|
412 Equipment
|
27
27
|
413 Machinery
|
28
28
|
414 Vehicles
|
29
29
|
415 Tools
|
30
30
|
416 Land
|
31
|
-
417 Construction in progress
|
31
|
+
417 Construction in progress us-gaap:ConstructionInProgressGross
|
32
32
|
418 Ships
|
33
33
|
420 Intangible Assets
|
34
34
|
421 Software
|
35
|
-
422 Goodwill
|
35
|
+
422 Goodwill us-gaap:Goodwill
|
36
36
|
423 Patents
|
37
37
|
424 借地権
|
38
38
|
425 商標権
|
@@ -52,10 +52,10 @@ code label xbrl_id consumption_tax income_tax
|
|
52
52
|
443 社債発行費
|
53
53
|
50 Current Liabilities
|
54
54
|
50XX UNSETTLED_IMPORT
|
55
|
-
510 Notes payable
|
55
|
+
510 Notes payable us-gaap:NotesPayable
|
56
56
|
511 Accounts payable - trade
|
57
|
-
512 Short-term borrowings
|
58
|
-
513 Commercial paper
|
57
|
+
512 Short-term borrowings us-gaap:ShortermBorrowings
|
58
|
+
513 Commercial paper us-gaap:CommercialPaper
|
59
59
|
514 Accounts payable - other
|
60
60
|
515 Income taxes payable
|
61
61
|
516 未払消費税等
|
@@ -66,7 +66,7 @@ code label xbrl_id consumption_tax income_tax
|
|
66
66
|
51B Deferred tax liabilities
|
67
67
|
70 Long-term Liabilities
|
68
68
|
711 Debt securities
|
69
|
-
712 Loans payable
|
69
|
+
712 Loans payable us-gaap:LoansPayable
|
70
70
|
713 退職給付引当金
|
71
71
|
714 Deferred tax liabilities
|
72
72
|
90 Net Assets
|
@@ -74,7 +74,7 @@ code label xbrl_id consumption_tax income_tax
|
|
74
74
|
911 Capital stock
|
75
75
|
912 Capital surplus
|
76
76
|
913 Retained earnings
|
77
|
-
914 Treasury stock
|
77
|
+
914 Treasury stock us-gaap:TreasuryStockValue
|
78
78
|
920 評価換算差額等
|
79
79
|
921 有価証券評価差額金
|
80
80
|
922 為替換算調整勘定
|
@@ -88,33 +88,38 @@ B12 Parts
|
|
88
88
|
B13 Labor
|
89
89
|
BA Gross profit
|
90
90
|
C0 Operating expenses
|
91
|
-
C11 Officers Compensation
|
92
|
-
C12 Salaries
|
91
|
+
C11 Officers Compensation us-gaap:OfficersCompensation
|
92
|
+
C12 Salaries us-gaap:SalariesAndWages
|
93
93
|
C13 Bonuses
|
94
94
|
C14 役員賞与
|
95
95
|
C15 退職金
|
96
96
|
C16 Legal welfare
|
97
|
-
C17 Travel
|
98
|
-
C18 Communication
|
99
|
-
C19 Repairs
|
100
|
-
C1A Advertising
|
97
|
+
C17 Travel us-gaap:TravelAndEntertainmentExpense
|
98
|
+
C18 Communication us-gaap:Communication
|
99
|
+
C19 Repairs us-gaap:CostOfPropertyRepairsAndMaintenance
|
100
|
+
C1A Advertising us-gaap:AdvertisingExpense
|
101
101
|
C1B Entertainment
|
102
102
|
C1C Packing-and-freight
|
103
103
|
C1D Welfare
|
104
104
|
C1E Rents
|
105
105
|
C1F Utilities
|
106
|
-
C1G Supplies
|
106
|
+
C1G Supplies us-gaap:SuppliesExpense
|
107
107
|
C1H Insurance
|
108
108
|
C1I Taxes
|
109
109
|
C1J 賃借料
|
110
110
|
C1K Books
|
111
111
|
C1L 貸倒損失
|
112
112
|
C1M 諸会費
|
113
|
-
C1N Fees and commisions
|
113
|
+
C1N Fees and commisions us-gaap:BankingFeesAndCommisions
|
114
114
|
C1O 外注費
|
115
115
|
C1P Depreciation
|
116
116
|
C1Q Miscellaneous
|
117
117
|
C1R 貸倒引当金繰入
|
118
|
+
C1S 支払報酬
|
119
|
+
C1T 研修費
|
120
|
+
C1U 採用費
|
121
|
+
C1V 業務委託費
|
122
|
+
C1W 会議費
|
118
123
|
CA Operating profit/loss
|
119
124
|
D0 営業外収益
|
120
125
|
D11 Interest income
|
@@ -139,4 +144,6 @@ G11 固定資産売却損
|
|
139
144
|
G12 固定資産除却損
|
140
145
|
G13 災害損失
|
141
146
|
GA Income before taxes
|
147
|
+
H0 Income Taxes
|
148
|
+
H11 Income Taxes Current
|
142
149
|
HA Net Income/Loss
|
@@ -1,5 +1,5 @@
|
|
1
1
|
code label xbrl_id consumption_tax income_tax
|
2
|
-
1 資産合計
|
2
|
+
1 資産合計 jppfs_cor:AssetsAbstract
|
3
3
|
10 流動資産 jppfs_cor:CurrentAssetsAbstract
|
4
4
|
10XX UNSETTLED_IMPORT
|
5
5
|
110 現金及び預金 jppfs_cor:CashAndDeposits
|
@@ -55,7 +55,7 @@ code label xbrl_id consumption_tax income_tax
|
|
55
55
|
442 創立費 jppfs_cor:DeferredOrganisationExpensesDA
|
56
56
|
442 新株発行費 jppfs_cor:StockIssuanceCostDA
|
57
57
|
443 社債発行費 jppfs_cor:BondIssuanceCostDA
|
58
|
-
5 負債・純資産合計
|
58
|
+
5 負債・純資産合計 jppfs_cor:LiabilitiesAndNetAssets
|
59
59
|
50 流動負債 jppfs_cor:CurrentLiabilitiesAbstract
|
60
60
|
50XX UNSETTLED_IMPORT
|
61
61
|
510 支払手形 jppfs_cor:NotePayableTrade
|
@@ -74,25 +74,24 @@ code label xbrl_id consumption_tax income_tax
|
|
74
74
|
712 長期借入金 jppfs_cor:LongTermLoansPayable
|
75
75
|
713 退職給付引当金 jppfs_cor:ProvisionForRetirementBenefits
|
76
76
|
714 繰延税金負債 jppfs_cor:DeferredTaxLiabilities
|
77
|
-
8ZZ 負債合計
|
78
|
-
90 純資産 jppfs_cor:NetAssetsAbstract
|
77
|
+
8ZZ 負債合計 jppfs_cor:LiabilitiesAbstract
|
79
78
|
91 株主資本 jppfs_cor:ShareholdersAbstract
|
80
79
|
911 資本金 jppfs_cor:CapitalStock
|
81
|
-
912 新株式申込証拠金
|
80
|
+
912 新株式申込証拠金 jppfs_cor:DepositForSubscriptionsToShares
|
82
81
|
913 資本剰余金 jppfs_cor:LegalCapitalSurplus
|
83
|
-
9131 資本準備金
|
84
|
-
9132 その他資本剰余金
|
82
|
+
9131 資本準備金 jppfs_cor:LegalCapitalSurplus
|
83
|
+
9132 その他資本剰余金 jppfs_cor:OtherCapitalSurplus
|
85
84
|
914 利益剰余金 jppfs_cor:RetainedEarnings
|
86
|
-
9141 利益準備金
|
87
|
-
9142 その他利益剰余金
|
85
|
+
9141 利益準備金 jppfs_cor:LegalRetainedEarnings
|
86
|
+
9142 その他利益剰余金 jppfs_cor:OtherRetainedEarningsAbstract
|
88
87
|
915 自己株式 jppfs_cor:TreasuryStock
|
89
|
-
916 自己株式申込証拠金
|
88
|
+
916 自己株式申込証拠金 jppfs_cor:DepositForSubscriptionsToTreasuryStock
|
90
89
|
92 評価換算差額等 jppfs_cor:ValuationAndTranslationAdjustments
|
91
90
|
921 有価証券評価差額金 jppfs_cor:ValuationDifferenceOnAvailableForSaleSecurities
|
92
91
|
922 為替換算調整勘定 jppfs_cor:ForeignCurrencyTranslationAdjustment
|
93
92
|
93 新株予約権 jppfs_cor:SubscriptionRightsToShares
|
94
93
|
940 非支配株主持分 jppfs_cor:NonControllingInterests
|
95
|
-
9ZZ 純資産合計
|
94
|
+
9ZZ 純資産合計 jppfs_cor:NetAssetsAbstract
|
96
95
|
A0 売上 jppfs_cor:NetSalesAbstract
|
97
96
|
A11 売上高 jppfs_cor:NetSales
|
98
97
|
B0 売上原価 jppfs_cor:CostOfSalesAbstract
|
@@ -130,7 +129,11 @@ C1O 外注費 jppfs_cor:SubcontructExpensesSGA
|
|
130
129
|
C1P 減価償却費 jppfs_cor:DepreciationSGA
|
131
130
|
C1Q 雑費 jppfs_cor:MiscellaneousExpensesSGA
|
132
131
|
C1R 貸倒引当金繰入 jppfs_cor:ProvisionOfAllowanceForDebtfulAccountsSGA
|
133
|
-
C1S 支払報酬
|
132
|
+
C1S 支払報酬 jppfs_cor:CompensationsSGA
|
133
|
+
C1T 研修費 jppfs_cor:TrainingExpensesSGA
|
134
|
+
C1U 採用費 jppfs_cor:RecruitingExpensesSGA
|
135
|
+
C1V 業務委託費 jppfs_cor:BusinessConsignmentExpensesSGA
|
136
|
+
C1W 会議費 jppfs_cor:ConferenceExpensesSGA
|
134
137
|
CA 営業利益 jppfs_cor:OperatingIncome
|
135
138
|
D0 営業外収益 jppfs_cor:NonOperatingIncomeAbstract
|
136
139
|
D11 受取利息 jppfs_cor:InterestIncomeNOI
|
@@ -154,5 +157,7 @@ G0 特別損失 jppfs_cor:ExtraordinaryLossAbstract
|
|
154
157
|
G11 固定資産売却損 jppfs_cor:LossOnSalesOfNoncurrentAssetsEL
|
155
158
|
G12 固定資産除却損 jppfs_cor:LossOnRetirementOfNoncurrentAssetsEL
|
156
159
|
G13 災害損失 jppfs_cor:LossOnDisasterEL
|
157
|
-
GA
|
160
|
+
GA 税引前利益 jppfs_cor:IncomeBeforeIncomeTaxes
|
161
|
+
H0 法人税等 jppfs_cor:IncomeTaxes
|
162
|
+
H11 法人税、住民税及び事業税 jppfs_cor:IncomeTaxesCurrent
|
158
163
|
HA 当期利益 jppfs_cor:ProfitLoss
|
data/lib/luca_book/version.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.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-11-
|
11
|
+
date: 2020-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lucarecord
|
@@ -82,9 +82,9 @@ files:
|
|
82
82
|
- lib/luca_book/console.rb
|
83
83
|
- lib/luca_book/dict.rb
|
84
84
|
- lib/luca_book/import.rb
|
85
|
+
- lib/luca_book/import_jp.rb
|
85
86
|
- lib/luca_book/journal.rb
|
86
87
|
- lib/luca_book/list.rb
|
87
|
-
- lib/luca_book/report.rb
|
88
88
|
- lib/luca_book/setup.rb
|
89
89
|
- lib/luca_book/state.rb
|
90
90
|
- lib/luca_book/templates/base-jp.xbrl.erb
|
data/lib/luca_book/report.rb
DELETED