lucarecord 0.2.14 → 0.2.19

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: 1b2e7e80da19b8c0adaebc6272a05e26f66c2e6a989fa416bfd77951ac5f88a0
4
- data.tar.gz: 699708346c68e5fa32105eec0d8a82aae8fd85c452f005a402f80a9ff7b19b95
3
+ metadata.gz: e5d79527ced912cddc0f5d33e7d557dd23fb2e2ae0ed0437f7c90eb44095469e
4
+ data.tar.gz: ce8fc1c4ec1264913024981a6769a36d6439d6d5b89a820bcfa7fcb6991151bb
5
5
  SHA512:
6
- metadata.gz: 59217fdab9258c37ceab07e35118961ae3ac6d6d1587f84235b31169dacf8a82f968a2e8b00f0710c0f7e587836d7d4834f4bf8d2f51e5fbd6f30d1a3100ea7b
7
- data.tar.gz: edbc54ec5c66e422a6975c8e53a33b32a063304d5c582ebf4f22596151d141de7d90404eaff8cdd7e8b10264f195da67803ba48a2e4426c6629d995f6cc03507
6
+ metadata.gz: f4f62de1a08971733954c469d2572f6aab8018379de928ab2413aca14d9123b08da67e5f85dcd8bf632c646732cf5c534f259bd83fb5eeff0d851e4d444b7e1c
7
+ data.tar.gz: 2ef832f91abef366760fbff0157c97c9e43a814b1df6f1c5244e0e0f7ad32db8459f2abee51fd1fd40812283b87b6b2a1140d6668b98ab98d86088d17d3bb0e4
@@ -0,0 +1,13 @@
1
+ ## LucaRecord 0.2.19
2
+
3
+ * `LucaSupport::Code.decode_id()`
4
+ * `LucaSupport::Code.encode_term()` for multiple months search. Old `scan_term()` removed.
5
+
6
+ ## LucaRecord 0.2.18
7
+
8
+ * `find()`, `create()`, `save()` now supports both of uuid / historical records. If specified `date:` keyword option to `create()`, then generate historical record. `find()`, `save()` identifies with 'id' attribute.
9
+
10
+ ## LucaRecord 0.2.17
11
+
12
+ * Change internal number format to BigDecimal.
13
+ * Number of Decimal is configurable through `decimal_number` in config.yml(default = 2). `country` setting can also affect.
@@ -1,4 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
3
+ require 'luca_support'
4
+ require 'luca_support/config'
2
5
  require 'luca_record/version'
3
6
 
4
7
  module LucaRecord
@@ -14,13 +14,13 @@ module LucaRecord
14
14
  include LucaSupport::Code
15
15
 
16
16
  def initialize(file = @filename)
17
- @path = file
18
- #@path = dict_path(file)
17
+ #@path = file
18
+ @path = self.class.dict_path(file)
19
19
  set_driver
20
20
  end
21
21
 
22
22
  def search(word, default_word = nil)
23
- res = max_score_code(word)
23
+ res = max_score_code(word.gsub(/[[:space:]]/, ''))
24
24
  if res[1] > 0.4
25
25
  res[0]
26
26
  else
@@ -65,7 +65,7 @@ module LucaRecord
65
65
  config[:type] ||= 'invalid'
66
66
  config[:debit_value] = @config['debit_value'].to_i if @config.dig('debit_value')
67
67
  config[:credit_value] = @config['credit_value'].to_i if @config.dig('credit_value')
68
- config[:note] = @config['note'].to_i if @config.dig('note')
68
+ config[:note] = @config['note'] if @config.dig('note')
69
69
  config[:encoding] = @config['encoding'] if @config.dig('encoding')
70
70
 
71
71
  config[:year] = @config['year'] if @config.dig('year')
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bigdecimal'
3
4
  require 'csv'
4
5
  require 'date'
5
6
  require 'fileutils'
@@ -20,24 +21,24 @@ module LucaRecord # :nodoc:
20
21
  end
21
22
 
22
23
  module ClassMethods
23
- #-----------------------------------------------------------------
24
+ # ----------------------------------------------------------------
24
25
  # :section: Query Methods
25
26
  # Provide sematic search interfaces.
26
27
  # <tt>basedir</tt> is set by class instance variable <tt>@dirname</tt>
27
28
  # of each concrete class.
28
- #-----------------------------------------------------------------
29
+ # ----------------------------------------------------------------
29
30
 
30
31
  # find ID based record. Support uuid and encoded date.
31
32
  def find(id, basedir = @dirname)
32
- return enum_for(:find, id, basedir) unless block_given?
33
+ return enum_for(:find, id, basedir).first unless block_given?
33
34
 
34
35
  if id.length >= 40
35
36
  open_hashed(basedir, id) do |f|
36
37
  yield load_data(f)
37
38
  end
38
- elsif id.length >= 9
39
- # TODO: need regexp match for more flexible coding(after AD9999)
40
- open_records(basedir, id[0, 5], id[5, 6]) do |f, path|
39
+ elsif id.length >= 7
40
+ parts = id.split('/')
41
+ open_records(basedir, parts[0], parts[1]) do |f, path|
41
42
  yield load_data(f, path)
42
43
  end
43
44
  else
@@ -53,8 +54,22 @@ module LucaRecord # :nodoc:
53
54
  def asof(year, month = nil, day = nil, basedir = @dirname)
54
55
  return enum_for(:search, year, month, day, nil, basedir) unless block_given?
55
56
 
56
- search(year, month, day, nil, basedir) do |data, path|
57
- yield data, path
57
+ search(year, month, day, nil, basedir) { |data, path| yield data, path }
58
+ end
59
+
60
+ # scan ranging data on multiple months
61
+ #
62
+ def term(start_year, start_month, end_year, end_month, code = nil, basedir = @dirname)
63
+ return enum_for(:term, start_year, start_month, end_year, end_month, code, basedir) unless block_given?
64
+
65
+ LucaSupport::Code.encode_term(start_year, start_month, end_year, end_month).each do |subdir|
66
+ open_records(basedir, subdir, nil, code) do |f, path|
67
+ if @record_type == 'raw'
68
+ yield f, path
69
+ else
70
+ yield load_data(f, path)
71
+ end
72
+ end
58
73
  end
59
74
  end
60
75
 
@@ -78,65 +93,117 @@ module LucaRecord # :nodoc:
78
93
  def all(basedir = @dirname)
79
94
  return enum_for(:all, basedir) unless block_given?
80
95
 
81
- open_all(basedir) do |f|
96
+ open_all(basedir) do |f|
82
97
  yield load_data(f)
83
98
  end
84
99
  end
85
100
 
86
- #-----------------------------------------------------------------
101
+ # ----------------------------------------------------------------
87
102
  # :section: Write Methods
88
103
  # <tt>basedir</tt> is set by class instance variable <tt>@dirname</tt>
89
104
  # of each concrete class.
90
- #-----------------------------------------------------------------
91
-
92
- # create hash based record
93
- def create(obj, basedir = @dirname)
94
- id = LucaSupport::Code.issue_random_id
95
- obj['id'] = id
96
- open_hashed(basedir, id, 'w') do |f|
97
- f.write(YAML.dump(obj.sort.to_h))
98
- end
99
- id
100
- end
105
+ # ----------------------------------------------------------------
101
106
 
102
- # define new transaction ID & write data at once
103
- def create_record!(obj, date_obj, codes = nil, basedir = @dirname)
104
- gen_record_file!(basedir, date_obj, codes) do |f|
105
- f.write(YAML.dump(obj.sort.to_h))
107
+ # create record both of uuid/date identified.
108
+ #
109
+ def create(obj, date: nil, codes: nil, basedir: @dirname)
110
+ validate_keys(obj)
111
+ if date
112
+ create_record(obj, date, codes, basedir)
113
+ else
114
+ obj['id'] = LucaSupport::Code.issue_random_id
115
+ open_hashed(basedir, obj['id'], 'w') do |f|
116
+ f.write(YAML.dump(LucaSupport::Code.readable(obj.sort.to_h)))
117
+ end
118
+ obj['id']
106
119
  end
107
120
  end
108
121
 
109
122
  def prepare_dir!(basedir, date_obj)
110
- dir_name = (Pathname(basedir) + encode_dirname(date_obj)).to_s
123
+ dir_name = (Pathname(basedir) + LucaSupport::Code.encode_dirname(date_obj)).to_s
111
124
  FileUtils.mkdir_p(dir_name) unless Dir.exist?(dir_name)
112
125
  dir_name
113
126
  end
114
127
 
115
128
  def add_status!(id, status, basedir = @dirname)
116
129
  path = abs_path(basedir) / id2path(id)
117
- origin = YAML.load_file(path, {})
130
+ origin = YAML.load_file(path, **{})
118
131
  newline = { status => DateTime.now.to_s }
119
132
  origin['status'] = [] if origin['status'].nil?
120
133
  origin['status'] << newline
121
134
  File.write(path, YAML.dump(origin.sort.to_h))
122
135
  end
123
136
 
124
- #-----------------------------------------------------------------
137
+ # update file with obj['id']
138
+ def save(obj, basedir = @dirname)
139
+ if obj['id'].nil?
140
+ create(obj, basedir)
141
+ else
142
+ validate_keys(obj)
143
+ if obj['id'].length < 40
144
+ parts = obj['id'].split('/')
145
+ raise 'invalid ID' if parts.length != 2
146
+
147
+ open_records(basedir, parts[0], parts[1], nil, 'w') do |f, path|
148
+ f.write(YAML.dump(LucaSupport::Code.readable(obj.sort.to_h)))
149
+ end
150
+ else
151
+ open_hashed(basedir, obj['id'], 'w') do |f|
152
+ f.write(YAML.dump(LucaSupport::Code.readable(obj.sort.to_h)))
153
+ end
154
+ end
155
+ end
156
+ obj['id']
157
+ end
158
+
159
+ # delete file by id
160
+ def delete(id, basedir = @dirname)
161
+ FileUtils.rm(Pathname(abs_path(basedir)) / id2path(id))
162
+ id
163
+ end
164
+
165
+ # change filename with new code set
166
+ #
167
+ def change_codes(id, new_codes, basedir = @dirname)
168
+ raise 'invalid id' if id.split('/').length != 2
169
+
170
+ newfile = new_codes.empty? ? id : id + '-' + new_codes.join('-')
171
+ Dir.chdir(abs_path(basedir)) do
172
+ origin = Dir.glob("#{id}*")
173
+ raise 'duplicated files' if origin.length != 1
174
+
175
+ File.rename(origin.first, newfile)
176
+ end
177
+ newfile
178
+ end
179
+
180
+ # ----------------------------------------------------------------
125
181
  # :section: Path Utilities
126
- #-----------------------------------------------------------------
182
+ # ----------------------------------------------------------------
127
183
 
128
- # convert ID to file path. Normal argument is as follows:
184
+ # Convert ID to file directory/filename path.
185
+ # 1st element of Array is used as directory, the others as filename.
186
+ # String without '/' is converted as git-like structure.
187
+ # Normal argument is as follows:
129
188
  #
130
- # [2020H, V001]
131
- # "2020H/V001"
132
- # "a7b806d04a044c6dbc4ce72932867719"
189
+ # ['2020H', 'V001', 'a7b806d04a044c6dbc4ce72932867719']
190
+ # => '2020H/V001-a7b806d04a044c6dbc4ce72932867719'
191
+ # 'a7b806d04a044c6dbc4ce72932867719'
192
+ # => 'a7b/806d04a044c6dbc4ce72932867719'
193
+ # '2020H/V001'
194
+ # => '2020H/V001'
133
195
  def id2path(id)
134
196
  if id.is_a?(Array)
135
- id.join('/')
197
+ case id.length
198
+ when 0..2
199
+ id.join('/')
200
+ else
201
+ [id[0], id[1..-1].join('-')].join('/')
202
+ end
136
203
  elsif id.include?('/')
137
204
  id
138
205
  else
139
- encode_hashed_path(id)
206
+ encode_hashed_path(id).join('/')
140
207
  end
141
208
  end
142
209
 
@@ -150,10 +217,6 @@ module LucaRecord # :nodoc:
150
217
  end
151
218
  end
152
219
 
153
- def encode_dirname(date_obj)
154
- date_obj.year.to_s + LucaSupport::Code.encode_month(date_obj)
155
- end
156
-
157
220
  # test if having required dirs/files under exec path
158
221
  def valid_project?(path = LucaSupport::Config::Pjdir)
159
222
  project_dir = Pathname(path)
@@ -166,6 +229,29 @@ module LucaRecord # :nodoc:
166
229
 
167
230
  private
168
231
 
232
+ # define new transaction ID & write data at once
233
+ # ID format is like '2020H/A001', which means record no.1 of 2020/10/10.
234
+ # Any data format can be written with block.
235
+ #
236
+ def create_record(obj, date_obj, codes = nil, basedir = @dirname)
237
+ FileUtils.mkdir_p(abs_path(basedir)) unless Dir.exist?(abs_path(basedir))
238
+ subdir = "#{date_obj.year}#{LucaSupport::Code.encode_month(date_obj)}"
239
+ filename = LucaSupport::Code.encode_date(date_obj) + new_record_id(basedir, date_obj)
240
+ obj['id'] = "#{subdir}/#{filename}" if obj.is_a? Hash
241
+ filename += '-' + codes.join('-') if codes
242
+ Dir.chdir(abs_path(basedir)) do
243
+ FileUtils.mkdir_p(subdir) unless Dir.exist?(subdir)
244
+ File.open(Pathname(subdir) / filename, 'w') do |f|
245
+ if block_given?
246
+ yield(f)
247
+ else
248
+ f.write(YAML.dump(LucaSupport::Code.readable(obj.sort.to_h)))
249
+ end
250
+ end
251
+ end
252
+ "#{subdir}/#{filename}"
253
+ end
254
+
169
255
  # open records with 'basedir/month/date-code' path structure.
170
256
  # Glob pattern can be specified like folloing examples.
171
257
  #
@@ -181,6 +267,7 @@ module LucaRecord # :nodoc:
181
267
 
182
268
  file_pattern = filename.nil? ? '*' : "#{filename}*"
183
269
  Dir.chdir(abs_path(basedir)) do
270
+ FileUtils.mkdir_p(subdir) if mode == 'w' && !Dir.exist?(subdir)
184
271
  Dir.glob("#{subdir}*/#{file_pattern}").sort.each do |subpath|
185
272
  next if skip_on_unmatch_code(subpath, code)
186
273
 
@@ -212,6 +299,17 @@ module LucaRecord # :nodoc:
212
299
  end
213
300
  end
214
301
 
302
+ # parse data dir and respond existing months
303
+ #
304
+ def scan_terms(query = nil, base_dir = @dirname)
305
+ pattern = query.nil? ? "*" : "#{query}*"
306
+ Dir.chdir(abs_path(base_dir)) do
307
+ Dir.glob(pattern).select { |dir|
308
+ FileTest.directory?(dir) && /^[0-9]/.match(dir)
309
+ }.sort.map { |str| decode_term(str) }
310
+ end
311
+ end
312
+
215
313
  # Decode basic format.
216
314
  # If specific decode is needed, override this method in each class.
217
315
  #
@@ -223,18 +321,18 @@ module LucaRecord # :nodoc:
223
321
  when 'json'
224
322
  # TODO: implement JSON parse
225
323
  else
226
- YAML.load(io.read)
324
+ LucaSupport::Code.decimalize(YAML.load(io.read)).tap { |obj| validate_keys(obj) }
227
325
  end
228
326
  end
229
327
 
230
- def gen_record_file!(basedir, date_obj, codes = nil)
231
- d = prepare_dir!(abs_path(basedir), date_obj)
232
- filename = LucaSupport::Code.encode_date(date_obj) + new_record_id(abs_path(basedir), date_obj)
233
- if codes
234
- filename += codes.inject('') { |fragment, code| "#{fragment}-#{code}" }
328
+ def validate_keys(obj)
329
+ return nil unless @required
330
+
331
+ keys = obj.keys
332
+ [].tap do |errors|
333
+ @required.each { |r| errors << r unless keys.include?(r) }
334
+ raise "Missing keys: #{errors.join(' ')}" unless errors.empty?
235
335
  end
236
- path = Pathname(d) + filename
237
- File.open(path.to_s, 'w') { |f| yield(f) }
238
336
  end
239
337
 
240
338
  # TODO: replace with data_dir method
@@ -254,8 +352,10 @@ module LucaRecord # :nodoc:
254
352
 
255
353
  # AUTO INCREMENT
256
354
  def new_record_no(basedir, date_obj)
257
- dir_name = (Pathname(basedir) + encode_dirname(date_obj)).to_s
258
- raise 'No target dir exists.' unless Dir.exist?(dir_name)
355
+ raise 'No target dir exists.' unless Dir.exist?(abs_path(basedir))
356
+
357
+ dir_name = (Pathname(abs_path(basedir)) / LucaSupport::Code.encode_dirname(date_obj)).to_s
358
+ return 1 unless Dir.exist?(dir_name)
259
359
 
260
360
  Dir.chdir(dir_name) do
261
361
  last_file = Dir.glob("#{LucaSupport::Code.encode_date(date_obj)}*").max
@@ -287,17 +387,6 @@ module LucaRecord # :nodoc:
287
387
  end
288
388
  end
289
389
 
290
- # parse data dir and respond existing months
291
- #
292
- def scan_terms(base_dir, query = nil)
293
- pattern = query.nil? ? "*" : "#{query}*"
294
- Dir.chdir(base_dir) do
295
- Dir.glob(pattern).select { |dir|
296
- FileTest.directory?(dir) && /^[0-9]/.match(dir)
297
- }.sort.map { |str| decode_term(str) }
298
- end
299
- end
300
-
301
390
  def load_config(path = nil)
302
391
  path = path.to_s
303
392
  if File.exist?(path)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LucaRecord
4
- VERSION = '0.2.14'
4
+ VERSION = '0.2.19'
5
5
  end
@@ -3,16 +3,24 @@
3
3
  require 'date'
4
4
  require 'securerandom'
5
5
  require 'digest/sha1'
6
+ require 'luca_support/config'
6
7
 
7
8
  # implement Luca IDs convention
8
9
  module LucaSupport
9
10
  module Code
10
11
  module_function
11
12
 
13
+ # Parse historical id into Array of date & transaction id.
14
+ #
15
+ def decode_id(id_str)
16
+ m = %r(^(?<year>[0-9]+)(?<month>[A-L])/?(?<day>[0-9A-V])(?<txid>[0-9A-Z]{,3})).match(id_str)
17
+ ["#{m[:year]}-#{decode_month(m[:month])}-#{decode_date(m[:day])}", decode_txid(m[:txid])]
18
+ end
19
+
12
20
  def encode_txid(num)
13
21
  txmap = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
14
22
  l = txmap.length
15
- txmap[num / (l**2)] + txmap[(num%(l**2)) / l] + txmap[num % l]
23
+ txmap[num / (l**2)] + txmap[(num % (l**2)) / l] + txmap[num % l]
16
24
  end
17
25
 
18
26
  def decode_txid(id)
@@ -44,7 +52,12 @@ module LucaSupport
44
52
  num.to_s.reverse.gsub!(/(\d{3})(?=\d)/, '\1,').reverse!
45
53
  end
46
54
 
55
+ # encode directory name from year and month.
47
56
  #
57
+ def encode_dirname(date_obj)
58
+ date_obj.year.to_s + encode_month(date_obj)
59
+ end
60
+
48
61
  # Month to code conversion.
49
62
  # Date, DateTime, String, Integer is valid input. If nil, returns empty String for consistency.
50
63
  #
@@ -63,6 +76,16 @@ module LucaSupport
63
76
  '0ABCDEFGHIJKL'.index(char)
64
77
  end
65
78
 
79
+ # Generate globbing phrase like ["2020[C-H]"] for range search.
80
+ #
81
+ def encode_term(start_year, start_month, end_year, end_month)
82
+ (start_year..end_year).to_a.map do |y|
83
+ g1 = y == start_year ? encode_month(start_month) : encode_month(1)
84
+ g2 = y == end_year ? encode_month(end_month) : encode_month(12)
85
+ "#{y}[#{g1}-#{g2}]"
86
+ end
87
+ end
88
+
66
89
  def decode_term(char)
67
90
  m = /^([0-9]{4})([A-La-l])/.match(char)
68
91
  [m[1].to_i, decode_month(m[2])]
@@ -72,8 +95,40 @@ module LucaSupport
72
95
  Digest::SHA1.hexdigest(SecureRandom.uuid)
73
96
  end
74
97
 
98
+ def decimalize(obj)
99
+ case obj.class.name
100
+ when 'Array'
101
+ obj.map { |i| decimalize(i) }
102
+ when 'Hash'
103
+ obj.inject({}) { |h, (k, v)| h[k] = decimalize(v); h }
104
+ when 'Integer'
105
+ BigDecimal(obj.to_s)
106
+ when 'String'
107
+ /^[0-9\.]+$/.match(obj) ? BigDecimal(obj) : obj
108
+ when 'Float'
109
+ raise 'already float'
110
+ else
111
+ obj
112
+ end
113
+ end
114
+
115
+ def readable(obj, len = LucaSupport::Config::DECIMAL_NUM)
116
+ case obj.class.name
117
+ when 'Array'
118
+ obj.map { |i| readable(i) }
119
+ when 'Hash'
120
+ obj.inject({}) { |h, (k, v)| h[k] = readable(v); h }
121
+ when 'BigDecimal'
122
+ parts = obj.round(len).to_s('F').split('.')
123
+ len < 1 ? parts.first : "#{parts[0]}.#{parts[1][0, len]}"
124
+ else
125
+ obj
126
+ end
127
+ end
128
+
75
129
  #
76
- # convert effective/defunct data into current hash on @date
130
+ # convert effective/defunct data into current hash on @date.
131
+ # not parse nested children.
77
132
  #
78
133
  def parse_current(dat)
79
134
  {}.tap do |processed|
@@ -92,11 +147,11 @@ module LucaSupport
92
147
  # - effective: 2020-1-1
93
148
  # rank: 5
94
149
  # point: 1000
95
- # => { 'effective' => 2020-1-1, 'rank' => 5, '' => 'point' => 1000 }
150
+ # => { 'effective' => 2020-1-1, 'rank' => 5, 'point' => 1000 }
96
151
  #
97
152
  def take_current(dat, item)
98
153
  target = dat.dig(item)
99
- if target.class.name == 'Array' && target.map(&:keys).flatten.include?('effective')
154
+ if target.is_a?(Array) && target.map(&:keys).flatten.include?('effective')
100
155
  latest = target
101
156
  .filter { |a| Date.parse(a.dig('effective').to_s) < @date }
102
157
  .max { |a, b| Date.parse(a.dig('effective').to_s) <=> Date.parse(b.dig('effective').to_s) }
@@ -1,11 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
4
+ require 'yaml'
5
+
3
6
  #
4
7
  # startup config
5
8
  #
6
9
  module LucaSupport
7
10
  module Config
8
11
  # Project top directory.
9
- Pjdir = Dir.pwd.freeze
12
+ Pjdir = ENV['LUCA_TEST_DIR'] || Dir.pwd.freeze
13
+ if File.exist?(Pathname(Pjdir) / 'config.yml')
14
+ # DECIMAL_NUM = YAML.load_file(Pathname(Pjdir) / 'config.yml', **{})['decimal_number']
15
+ COUNTRY = YAML.load_file(Pathname(Pjdir) / 'config.yml', **{})['country']
16
+ DECIMAL_NUM ||= 0 if COUNTRY == 'jp'
17
+ end
18
+ DECIMAL_NUM ||= 2
10
19
  end
11
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lucarecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.14
4
+ version: 0.2.19
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-10-07 00:00:00.000000000 Z
11
+ date: 2020-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mail
@@ -28,44 +28,44 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.17'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.17'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 12.3.3
47
+ version: '5.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 12.3.3
54
+ version: '5.0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: minitest
56
+ name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '5.0'
61
+ version: 12.3.3
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '5.0'
68
+ version: 12.3.3
69
69
  description: 'ERP File operation framework
70
70
 
71
71
  '