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 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