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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 866a73f9e372f2ac755ed301c9e9b88bebb556b53a5ffd604391c45eda927653
4
- data.tar.gz: 41b02c0e5c567dbfedf37fe4148d11270a0f8776c6fcc78f630354e281aad5d3
3
+ metadata.gz: 55e730a696b4537183e9a298cff7d715c2a93dfa22fabc10cc889fd18c72b1a1
4
+ data.tar.gz: f5e579c528ad978533f7df60eed6b4a494dd723a4fdef15180622737fd9be32a
5
5
  SHA512:
6
- metadata.gz: 1f295b8ab521f4b95c81ec57c57579ebf87ae01c3f1acf2fbc564bf076731d1b1d089e0959660752529e190eecfa3e107ee184b6f91484f9bdc61977eda80886
7
- data.tar.gz: '0820bc3b42bfd48b0cf8f2924774acc8887c6fda373ec71fcebab5152b46e292096b68f174ac643613fda4ef72dc62a79300b4fa82e306d144f2fe404a770213'
6
+ metadata.gz: 607110ed2c686b35c1be749b16bd6f4c0827450e55277d44c62ddb5acfb06fbb67d601c9fe475c453f5999afa23a1bf83923d7251ba72a7a24267e0cfc8b4057
7
+ data.tar.gz: d8fe5540370bc81494847b5f9d975667d19bda4e7979fc852556e81b2adbd644b87ca11bdf7601334454cfe545070698e0e20570895fd2e0eb4bb790eea19711
@@ -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]'
@@ -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[:value].each_slice(6) do |v|
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[:value].inject(:+)] + Array.new(h[:value].length)
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[:value].each_slice(6).with_index(0) do |v, i|
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), value: v}
101
+ {code: k, label: @report.dict.dig(k, :label), amount: v}
102
102
  end
103
103
  end
104
104
 
@@ -15,10 +15,10 @@ module LucaBook
15
15
  # must be specified with label
16
16
  # :debit_label
17
17
  # for double entry data
18
- # * debit_value
18
+ # * debit_amount
19
19
  # :credit_label
20
20
  # for double entry data
21
- # * credit_value
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[: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')
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
 
@@ -35,13 +35,13 @@ module LucaBook
35
35
  # "debit" : [
36
36
  # {
37
37
  # "label": "savings accounts",
38
- # "value": 20000
38
+ # "amount": 20000
39
39
  # }
40
40
  # ],
41
41
  # "credit" : [
42
42
  # {
43
43
  # "label": "trade notes receivable",
44
- # "value": 20000
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[:credit_value]) || []).empty?
79
- value = BigDecimal(row[@config[:debit_value]])
78
+ if (row.dig(@config[:credit_amount]) || []).empty?
79
+ amount = BigDecimal(row[@config[:debit_amount]])
80
80
  debit = true
81
81
  else
82
- value = BigDecimal(row[@config[:credit_value]])
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, value)
85
+ code, options = search_code(row[@config[:label]], default_label, amount)
86
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
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, 'value' => value }]
91
- data_c ||= [{ 'code' => counter_code, 'value' => value }]
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'] = "LucaBook::Import/#{@dict_name}"
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
- 'value' => row.dig(@config[:debit_value])
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
- 'value' => row.dig(@config[:credit_value])
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}"
@@ -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, '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
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, '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
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, 'value' => amount1 }
55
- res1 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 0
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, 'value' => amount2 }
62
- res2 << { 'code' => gensen_code, 'value' => gensen_amount } if gensen_idx == 1
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, 'value' => amount1 }
72
- res1 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 0
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, 'value' => amount2 }
78
- res2 << { 'code' => consumption_code, 'value' => consumption_amount } if consumption_idx == 1
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
@@ -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'], 'value'))
46
- credit_amount = LucaSupport::Code.decimalize(serialize_on_key(d['credit'], 'value'))
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('', col_sep: "\t", headers: false) do |f|
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
- ['x-customer', 'x-editor'].each do |x_header|
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
- debit_values = serialize_on_key(obj['debit'], 'value').compact
99
+ debit_amount = serialize_on_key(obj['debit'], 'amount').compact
77
100
  raise 'NoDebitCode' if debit_codes.empty?
78
- raise 'NoDebitValue' if debit_values.empty?
79
- raise 'UnmatchDebit' if debit_codes.length != debit_values.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
- credit_values = serialize_on_key(obj['credit'], 'value').compact
104
+ credit_amount = serialize_on_key(obj['credit'], 'amount').compact
82
105
  raise 'NoCreditCode' if credit_codes.empty?
83
- raise 'NoCreditValue' if credit_values.empty?
84
- raise 'UnmatchCredit' if credit_codes.length != credit_values.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|
@@ -7,11 +7,12 @@ require 'luca_record'
7
7
  require 'luca_record/dict'
8
8
  require 'luca_book'
9
9
 
10
- # Journal List on specified term
11
- #
12
- module LucaBook
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
- # Journal List on specified term
11
- #
12
- module LucaBook
10
+ module LucaBook #:nodoc:
11
+ # Journal List on specified term
12
+ #
13
13
  class ListByHeader < LucaBook::Journal
14
14
  @dirname = 'journals'
15
15
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LucaBook
4
- VERSION = '0.2.23'
4
+ VERSION = '0.2.24'
5
5
  end
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.23
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: 2020-11-29 00:00:00.000000000 Z
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.1.2
118
+ rubygems_version: 3.2.3
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: Book keep