lucabook 0.2.23 → 0.2.24
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 +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
|