lucabook 0.2.23 → 0.2.24
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 +19 -0
- data/lib/luca_book/console.rb +4 -4
- data/lib/luca_book/dict.rb +4 -4
- data/lib/luca_book/import.rb +15 -13
- data/lib/luca_book/import_jp.rb +14 -14
- data/lib/luca_book/journal.rb +52 -15
- data/lib/luca_book/list.rb +14 -3
- data/lib/luca_book/list_by_header.rb +3 -3
- data/lib/luca_book/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55e730a696b4537183e9a298cff7d715c2a93dfa22fabc10cc889fd18c72b1a1
|
4
|
+
data.tar.gz: f5e579c528ad978533f7df60eed6b4a494dd723a4fdef15180622737fd9be32a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 607110ed2c686b35c1be749b16bd6f4c0827450e55277d44c62ddb5acfb06fbb67d601c9fe475c453f5999afa23a1bf83923d7251ba72a7a24267e0cfc8b4057
|
7
|
+
data.tar.gz: d8fe5540370bc81494847b5f9d975667d19bda4e7979fc852556e81b2adbd644b87ca11bdf7601334454cfe545070698e0e20570895fd2e0eb4bb790eea19711
|
data/exe/luca-book
CHANGED
@@ -39,6 +39,15 @@ class LucaCmd
|
|
39
39
|
render(LucaBook::State.range(*args).stats(params[:level]), params)
|
40
40
|
end
|
41
41
|
end
|
42
|
+
|
43
|
+
def self.add_header(args, params)
|
44
|
+
args = gen_range(params[:n] || 1) if args.empty?
|
45
|
+
if params['code']
|
46
|
+
LucaBook::List.add_header(*args, code: params['code'], header_key: params[:key], header_val: params[:value])
|
47
|
+
else
|
48
|
+
puts 'no code specified.'
|
49
|
+
end
|
50
|
+
end
|
42
51
|
end
|
43
52
|
|
44
53
|
class Report < LucaCmd
|
@@ -107,6 +116,16 @@ when /journals?/, 'j'
|
|
107
116
|
args = opt.parse!(ARGV)
|
108
117
|
LucaCmd::Journal.list(args, params)
|
109
118
|
end
|
119
|
+
when 'set'
|
120
|
+
OptionParser.new do |opt|
|
121
|
+
opt.banner = 'Usage: luca-book journals set [options] [YYYY M]'
|
122
|
+
opt.on('-c', '--code VAL', 'search with code') { |v| params['code'] = v }
|
123
|
+
opt.on('--header VAL', 'header key') { |v| params[:key] = v }
|
124
|
+
opt.on('--val VAL', 'header value') { |v| params[:value] = v }
|
125
|
+
opt.on_tail('set header to journals on specified code.')
|
126
|
+
args = opt.parse!(ARGV)
|
127
|
+
LucaCmd::Journal.add_header(args, params)
|
128
|
+
end
|
110
129
|
when 'stats'
|
111
130
|
OptionParser.new do |opt|
|
112
131
|
opt.banner = 'Usage: luca-book journals stats [options] [YYYY M]'
|
data/lib/luca_book/console.rb
CHANGED
@@ -49,7 +49,7 @@ class LucaBookConsole
|
|
49
49
|
print " " if h[:code].length > 3
|
50
50
|
end
|
51
51
|
puts cnsl_label(h[:label], h[:code])
|
52
|
-
h[:
|
52
|
+
h[:amount].each_slice(6) do |v|
|
53
53
|
puts "#{cnsl_fmt("", 14)} #{v.map{|v| cnsl_fmt(v, 14)}.join}"
|
54
54
|
end
|
55
55
|
end
|
@@ -72,13 +72,13 @@ class LucaBookConsole
|
|
72
72
|
end
|
73
73
|
convert_collection(report).each do |h|
|
74
74
|
if /^[A-Z]/.match(h[:code])
|
75
|
-
total = [h[:
|
75
|
+
total = [h[:amount].inject(:+)] + Array.new(h[:amount].length)
|
76
76
|
if /[^0]$/.match(h[:code])
|
77
77
|
print " "
|
78
78
|
print " " if h[:code].length > 3
|
79
79
|
end
|
80
80
|
puts cnsl_label(h[:label], h[:code])
|
81
|
-
h[:
|
81
|
+
h[:amount].each_slice(6).with_index(0) do |v, i|
|
82
82
|
puts "#{cnsl_fmt(total[i], 14)} #{v.map{|v| cnsl_fmt(v, 14)}.join}"
|
83
83
|
end
|
84
84
|
end
|
@@ -98,7 +98,7 @@ class LucaBookConsole
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
}.sort.map do |k,v|
|
101
|
-
{code: k, label: @report.dict.dig(k, :label),
|
101
|
+
{code: k, label: @report.dict.dig(k, :label), amount: v}
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
data/lib/luca_book/dict.rb
CHANGED
@@ -15,10 +15,10 @@ module LucaBook
|
|
15
15
|
# must be specified with label
|
16
16
|
# :debit_label
|
17
17
|
# for double entry data
|
18
|
-
# *
|
18
|
+
# * debit_amount
|
19
19
|
# :credit_label
|
20
20
|
# for double entry data
|
21
|
-
# *
|
21
|
+
# * credit_amount
|
22
22
|
# :note
|
23
23
|
# can be the same column as another label
|
24
24
|
#
|
@@ -41,8 +41,8 @@ module LucaBook
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
config[:type] ||= 'invalid'
|
44
|
-
config[:
|
45
|
-
config[:
|
44
|
+
config[:debit_amount] = @config['debit_amount'].to_i if @config.dig('debit_amount')
|
45
|
+
config[:credit_amount] = @config['credit_amount'].to_i if @config.dig('credit_amount')
|
46
46
|
config[:note] = @config['note'] if @config.dig('note')
|
47
47
|
config[:encoding] = @config['encoding'] if @config.dig('encoding')
|
48
48
|
|
data/lib/luca_book/import.rb
CHANGED
@@ -35,13 +35,13 @@ module LucaBook
|
|
35
35
|
# "debit" : [
|
36
36
|
# {
|
37
37
|
# "label": "savings accounts",
|
38
|
-
# "
|
38
|
+
# "amount": 20000
|
39
39
|
# }
|
40
40
|
# ],
|
41
41
|
# "credit" : [
|
42
42
|
# {
|
43
43
|
# "label": "trade notes receivable",
|
44
|
-
# "
|
44
|
+
# "amount": 20000
|
45
45
|
# }
|
46
46
|
# ],
|
47
47
|
# "note": "settlement for the last month trade"
|
@@ -75,20 +75,21 @@ module LucaBook
|
|
75
75
|
# convert single entry data
|
76
76
|
#
|
77
77
|
def parse_single(row)
|
78
|
-
if (row.dig(@config[:
|
79
|
-
|
78
|
+
if (row.dig(@config[:credit_amount]) || []).empty?
|
79
|
+
amount = BigDecimal(row[@config[:debit_amount]])
|
80
80
|
debit = true
|
81
81
|
else
|
82
|
-
|
82
|
+
amount = BigDecimal(row[@config[:credit_amount]])
|
83
83
|
end
|
84
84
|
default_label = debit ? @config.dig(:default_debit) : @config.dig(:default_credit)
|
85
|
-
code, options = search_code(row[@config[:label]], default_label,
|
85
|
+
code, options = search_code(row[@config[:label]], default_label, amount)
|
86
86
|
counter_code = @code_map.dig(@config[:counter_label])
|
87
|
-
if
|
88
|
-
|
87
|
+
if options
|
88
|
+
x_customer = options[:'x-customer'] if options[:'x-customer']
|
89
|
+
data, data_c = tax_extension(code, counter_code, amount, options) if respond_to? :tax_extension
|
89
90
|
end
|
90
|
-
data ||= [{ 'code' => code, '
|
91
|
-
data_c ||= [{ 'code' => counter_code, '
|
91
|
+
data ||= [{ 'code' => code, 'amount' => amount }]
|
92
|
+
data_c ||= [{ 'code' => counter_code, 'amount' => amount }]
|
92
93
|
{}.tap do |d|
|
93
94
|
d['date'] = parse_date(row)
|
94
95
|
if debit
|
@@ -99,7 +100,8 @@ module LucaBook
|
|
99
100
|
d['credit'] = data
|
100
101
|
end
|
101
102
|
d['note'] = Array(@config[:note]).map{ |col| row[col] }.join(' ')
|
102
|
-
d['x-editor'
|
103
|
+
d['headers'] = { 'x-editor' => "LucaBook::Import/#{@dict_name}" }
|
104
|
+
d['headers']['x-customer'] = x_customer if x_customer
|
103
105
|
end
|
104
106
|
end
|
105
107
|
|
@@ -110,11 +112,11 @@ module LucaBook
|
|
110
112
|
d['date'] = parse_date(row)
|
111
113
|
d['debit'] = {
|
112
114
|
'code' => search_code(row[@config[:label]], @config.dig(:default_debit)) || DEBIT_DEFAULT,
|
113
|
-
'
|
115
|
+
'amount' => row.dig(@config[:debit_amount])
|
114
116
|
}
|
115
117
|
d['credit'] = {
|
116
118
|
'code' => search_code(row[@config[:label]], @config.dig(:default_credit)) || CREDIT_DEFAULT,
|
117
|
-
'
|
119
|
+
'amount' => row.dig(@config[:credit_amount])
|
118
120
|
}
|
119
121
|
d['note'] = Array(@config[:note]).map{ |col| row[col] }.join(' ')
|
120
122
|
d['x-editor'] = "LucaBook::Import/#{@dict_name}"
|
data/lib/luca_book/import_jp.rb
CHANGED
@@ -31,17 +31,17 @@ module LucaBook
|
|
31
31
|
amount1 = amount
|
32
32
|
amount1 -= consumption_amount if consumption_idx == 0
|
33
33
|
amount1 += gensen_amount if gensen_idx == 1
|
34
|
-
res1 << { 'code' => code1, '
|
35
|
-
res1 << { 'code' => consumption_code, '
|
36
|
-
res1 << { 'code' => gensen_code, '
|
34
|
+
res1 << { 'code' => code1, 'amount' => amount1 }
|
35
|
+
res1 << { 'code' => consumption_code, 'amount' => consumption_amount } if consumption_idx == 0
|
36
|
+
res1 << { 'code' => gensen_code, 'amount' => gensen_amount } if gensen_idx == 0
|
37
37
|
end
|
38
38
|
res << [].tap do |res2|
|
39
39
|
amount2 = amount
|
40
40
|
amount2 -= consumption_amount if consumption_idx == 1
|
41
41
|
amount2 += gensen_amount if gensen_idx == 0
|
42
|
-
res2 << { 'code' => code2, '
|
43
|
-
res2 << { 'code' => consumption_code, '
|
44
|
-
res2 << { 'code' => gensen_code, '
|
42
|
+
res2 << { 'code' => code2, 'amount' => amount2 }
|
43
|
+
res2 << { 'code' => consumption_code, 'amount' => consumption_amount } if consumption_idx == 1
|
44
|
+
res2 << { 'code' => gensen_code, 'amount' => gensen_amount } if gensen_idx == 1
|
45
45
|
end
|
46
46
|
end
|
47
47
|
elsif options[:tax_options].include?('jp-gensen')
|
@@ -51,15 +51,15 @@ module LucaBook
|
|
51
51
|
res << [].tap do |res1|
|
52
52
|
amount1 = amount
|
53
53
|
amount1 += gensen_amount if gensen_idx == 1
|
54
|
-
res1 << { 'code' => code, '
|
55
|
-
res1 << { 'code' => gensen_code, '
|
54
|
+
res1 << { 'code' => code, 'amount' => amount1 }
|
55
|
+
res1 << { 'code' => gensen_code, 'amount' => gensen_amount } if gensen_idx == 0
|
56
56
|
end
|
57
57
|
res << [].tap do |res2|
|
58
58
|
amount2 = amount
|
59
59
|
amount2 += gensen_amount if gensen_idx == 0
|
60
60
|
mount2 ||= amount
|
61
|
-
res2 << { 'code' => code2, '
|
62
|
-
res2 << { 'code' => gensen_code, '
|
61
|
+
res2 << { 'code' => code2, 'amount' => amount2 }
|
62
|
+
res2 << { 'code' => gensen_code, 'amount' => gensen_amount } if gensen_idx == 1
|
63
63
|
end
|
64
64
|
end
|
65
65
|
elsif options[:tax_options].include?('jp-consumption')
|
@@ -68,14 +68,14 @@ module LucaBook
|
|
68
68
|
res << [].tap do |res1|
|
69
69
|
amount1 = amount
|
70
70
|
amount1 -= consumption_amount if consumption_idx == 0
|
71
|
-
res1 << { 'code' => code1, '
|
72
|
-
res1 << { 'code' => consumption_code, '
|
71
|
+
res1 << { 'code' => code1, 'amount' => amount1 }
|
72
|
+
res1 << { 'code' => consumption_code, 'amount' => consumption_amount } if consumption_idx == 0
|
73
73
|
end
|
74
74
|
res << [].tap do |res2|
|
75
75
|
amount2 = amount
|
76
76
|
amount2 -= consumption_amount if consumption_idx == 1
|
77
|
-
res2 << { 'code' => code2, '
|
78
|
-
res2 << { 'code' => consumption_code, '
|
77
|
+
res2 << { 'code' => code2, 'amount' => amount2 }
|
78
|
+
res2 << { 'code' => consumption_code, 'amount' => consumption_amount } if consumption_idx == 1
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
data/lib/luca_book/journal.rb
CHANGED
@@ -1,13 +1,21 @@
|
|
1
|
-
#
|
2
|
-
# manipulate files based on transaction date
|
3
|
-
#
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
3
|
require 'csv'
|
6
4
|
require 'date'
|
7
5
|
require 'luca_record'
|
8
6
|
|
9
|
-
module LucaBook
|
7
|
+
module LucaBook #:nodoc:
|
8
|
+
# Journal has several annotations on headers:
|
9
|
+
#
|
10
|
+
# x-customer::
|
11
|
+
# Identifying customer.
|
12
|
+
# x-editor::
|
13
|
+
# Application name editing the journal.
|
14
|
+
# x-tax::
|
15
|
+
# For tracking tax related transaction.
|
16
|
+
#
|
10
17
|
class Journal < LucaRecord::Base
|
18
|
+
ACCEPTED_HEADERS = ['x-customer', 'x-editor', 'x-tax']
|
11
19
|
@dirname = 'journals'
|
12
20
|
|
13
21
|
# create journal from hash
|
@@ -41,20 +49,22 @@ module LucaBook
|
|
41
49
|
open_records(@dirname, parts[0], parts[1], codes, 'w') { |f, _path| f.write journal2csv(d) }
|
42
50
|
end
|
43
51
|
|
52
|
+
# Convert journal object to TSV format.
|
53
|
+
#
|
44
54
|
def self.journal2csv(d)
|
45
|
-
debit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['debit'], '
|
46
|
-
credit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['credit'], '
|
55
|
+
debit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['debit'], 'amount'))
|
56
|
+
credit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['credit'], 'amount'))
|
47
57
|
raise 'BalanceUnmatch' if debit_amount.inject(:+) != credit_amount.inject(:+)
|
48
58
|
|
49
59
|
debit_code = serialize_on_key(d['debit'], 'code')
|
50
60
|
credit_code = serialize_on_key(d['credit'], 'code')
|
51
61
|
|
52
|
-
csv = CSV.generate(
|
62
|
+
csv = CSV.generate(String.new, col_sep: "\t", headers: false) do |f|
|
53
63
|
f << debit_code
|
54
64
|
f << LucaSupport::Code.readable(debit_amount)
|
55
65
|
f << credit_code
|
56
66
|
f << LucaSupport::Code.readable(credit_amount)
|
57
|
-
|
67
|
+
ACCEPTED_HEADERS.each do |x_header|
|
58
68
|
f << [x_header, d['headers'][x_header]] if d.dig('headers', x_header)
|
59
69
|
end
|
60
70
|
f << []
|
@@ -62,6 +72,19 @@ module LucaBook
|
|
62
72
|
end
|
63
73
|
end
|
64
74
|
|
75
|
+
# Set accepted header with key/value
|
76
|
+
#
|
77
|
+
def self.add_header(journal_hash, key, val)
|
78
|
+
return journal_hash if val.nil?
|
79
|
+
return journal_hash unless ACCEPTED_HEADERS.include?(key)
|
80
|
+
|
81
|
+
journal_hash.tap do |o|
|
82
|
+
o[:headers] = {} unless o.dig(:headers)
|
83
|
+
o[:headers][key] = val
|
84
|
+
save o
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
65
88
|
def self.update_codes(obj)
|
66
89
|
debit_code = serialize_on_key(obj[:debit], :code)
|
67
90
|
credit_code = serialize_on_key(obj[:credit], :code)
|
@@ -73,15 +96,15 @@ module LucaBook
|
|
73
96
|
raise 'NoDebitKey' unless obj.key?('debit')
|
74
97
|
raise 'NoCreditKey' unless obj.key?('credit')
|
75
98
|
debit_codes = serialize_on_key(obj['debit'], 'code').compact
|
76
|
-
|
99
|
+
debit_amount = serialize_on_key(obj['debit'], 'amount').compact
|
77
100
|
raise 'NoDebitCode' if debit_codes.empty?
|
78
|
-
raise '
|
79
|
-
raise 'UnmatchDebit' if debit_codes.length !=
|
101
|
+
raise 'NoDebitAmount' if debit_amount.empty?
|
102
|
+
raise 'UnmatchDebit' if debit_codes.length != debit_amount.length
|
80
103
|
credit_codes = serialize_on_key(obj['credit'], 'code').compact
|
81
|
-
|
104
|
+
credit_amount = serialize_on_key(obj['credit'], 'amount').compact
|
82
105
|
raise 'NoCreditCode' if credit_codes.empty?
|
83
|
-
raise '
|
84
|
-
raise 'UnmatchCredit' if credit_codes.length !=
|
106
|
+
raise 'NoCreditAmount' if credit_amount.empty?
|
107
|
+
raise 'UnmatchCredit' if credit_codes.length != credit_amount.length
|
85
108
|
end
|
86
109
|
|
87
110
|
# collect values on specified key
|
@@ -90,7 +113,21 @@ module LucaBook
|
|
90
113
|
array_of_hash.map { |h| h[key] }
|
91
114
|
end
|
92
115
|
|
93
|
-
# override de-serializing journal format
|
116
|
+
# override de-serializing journal format. Sample format is:
|
117
|
+
#
|
118
|
+
# {
|
119
|
+
# id: '2021A/V001',
|
120
|
+
# headers: {
|
121
|
+
# 'x-customer' => 'Some Customer Co.'
|
122
|
+
# },
|
123
|
+
# debit: [
|
124
|
+
# { code: 'A12', amount: 1000 }
|
125
|
+
# ],
|
126
|
+
# credit: [
|
127
|
+
# { code: '311', amount: 1000 }
|
128
|
+
# ],
|
129
|
+
# note: 'note for each journal'
|
130
|
+
# }
|
94
131
|
#
|
95
132
|
def self.load_data(io, path)
|
96
133
|
{}.tap do |record|
|
data/lib/luca_book/list.rb
CHANGED
@@ -7,11 +7,12 @@ require 'luca_record'
|
|
7
7
|
require 'luca_record/dict'
|
8
8
|
require 'luca_book'
|
9
9
|
|
10
|
-
|
11
|
-
#
|
12
|
-
|
10
|
+
module LucaBook #:nodoc:
|
11
|
+
# Journal List on specified term
|
12
|
+
#
|
13
13
|
class List < LucaBook::Journal
|
14
14
|
@dirname = 'journals'
|
15
|
+
attr_reader :data
|
15
16
|
|
16
17
|
def initialize(data, start_date, code = nil)
|
17
18
|
@data = data
|
@@ -31,6 +32,16 @@ module LucaBook
|
|
31
32
|
new data, Date.new(from_year.to_i, from_month.to_i, 1), code
|
32
33
|
end
|
33
34
|
|
35
|
+
def self.add_header(from_year, from_month, to_year = from_year, to_month = from_month, code: nil, header_key: nil, header_val: nil)
|
36
|
+
return nil if code.nil?
|
37
|
+
return nil unless Journal::ACCEPTED_HEADERS.include?(header_key)
|
38
|
+
|
39
|
+
term(from_year, from_month, to_year, to_month, code: code)
|
40
|
+
.data.each do |journal|
|
41
|
+
Journal.add_header(journal, header_key, header_val)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
34
45
|
def list_by_code
|
35
46
|
calc_code
|
36
47
|
convert_label
|
@@ -7,9 +7,9 @@ require 'luca_record'
|
|
7
7
|
require 'luca_record/dict'
|
8
8
|
require 'luca_book'
|
9
9
|
|
10
|
-
|
11
|
-
#
|
12
|
-
|
10
|
+
module LucaBook #:nodoc:
|
11
|
+
# Journal List on specified term
|
12
|
+
#
|
13
13
|
class ListByHeader < LucaBook::Journal
|
14
14
|
@dirname = 'journals'
|
15
15
|
|
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.24
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chuma Takahiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lucarecord
|
@@ -115,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '0'
|
117
117
|
requirements: []
|
118
|
-
rubygems_version: 3.
|
118
|
+
rubygems_version: 3.2.3
|
119
119
|
signing_key:
|
120
120
|
specification_version: 4
|
121
121
|
summary: Book keep
|