lucabook 0.2.17 → 0.2.22
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 +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