rsr_group 1.8.0 → 2.0.1

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
  SHA1:
3
- metadata.gz: fad2958461833a387cb30e337cc04bbefb1a674a
4
- data.tar.gz: b72595cc6a0dbc0016728fb3519d28e03ff01d94
3
+ metadata.gz: 27991f59b6bc1ffd9323f289032eb43c2cb02eff
4
+ data.tar.gz: b51ac996718c674f4a3e635780e35a7cea841793
5
5
  SHA512:
6
- metadata.gz: 581611d9c64fec310a2d8b5e492fb44ac5507f5bc14ef758dc8352c8863066f2dab397fc5c5092f8da85fbac76d0a7e6ea18454c30e52dc0538deb3e6cdb3cc3
7
- data.tar.gz: 590fb42cc224d76ca798064a050077c47eb23c691fb064eabfa50d76e4585925e3ae614146cea4027e1214197e7511487095382d1c8b551526e34d31c587f57c
6
+ metadata.gz: d9b6f14459886bbc9f3d94ff15d24e67c7c6627877b71298f75fc3dd2dbc6476d70f53df80a2c9c0259eff6ab2fe735bfafb5b6bdfbeaeed218af8eccf2a3615
7
+ data.tar.gz: 6be675b380406ffad1bd4029d7d20c582c10477b481157d8c9666eba28ae4a81109764b55e8c9c1536381ae1c18e7041993df47a64a6e31548ca05b10ba711cb
data/lib/rsr_group.rb CHANGED
@@ -10,6 +10,7 @@ require 'rsr_group/constants'
10
10
  require 'rsr_group/chunker'
11
11
  require 'rsr_group/data_row'
12
12
  require 'rsr_group/department'
13
+ require 'rsr_group/catalog'
13
14
  require 'rsr_group/inventory'
14
15
  require 'rsr_group/order'
15
16
  require 'rsr_group/order_detail'
@@ -0,0 +1,86 @@
1
+ module RsrGroup
2
+ class Catalog < Base
3
+
4
+ KEYDEALER_DIR = 'keydealer'.freeze
5
+ INVENTORY_DIR = 'ftpdownloads'.freeze
6
+ INVENTORY_FILENAME = 'rsrinventory-new.txt'.freeze
7
+ KEYDEALER_FILENAME = 'rsrinventory-keydlr-new.txt'.freeze
8
+
9
+ def initialize(options = {})
10
+ requires!(options, :username, :password)
11
+
12
+ @options = options
13
+ end
14
+
15
+ def self.all(chunk_size = 15, options = {}, &block)
16
+ requires!(options, :username, :password)
17
+ new(options).all(chunk_size, &block)
18
+ end
19
+
20
+ def all(chunk_size, &block)
21
+ connect(@options) do |ftp|
22
+ begin
23
+ chunker = RsrGroup::Chunker.new(chunk_size)
24
+ csv_tempfile = Tempfile.new
25
+
26
+ if ftp.nlst.include?(KEYDEALER_DIR)
27
+ ftp.chdir(KEYDEALER_DIR)
28
+ ftp.getbinaryfile(KEYDEALER_FILENAME, csv_tempfile.path)
29
+ else
30
+ ftp.chdir(INVENTORY_DIR)
31
+ ftp.getbinaryfile(INVENTORY_FILENAME, csv_tempfile.path)
32
+ end
33
+
34
+ chunker.total_count = File.readlines(csv_tempfile).size
35
+
36
+ CSV.readlines(csv_tempfile, col_sep: ';', quote_char: "\x00").to_enum.with_index(1).each do |row, current_line|
37
+ if chunker.is_full?
38
+ yield(chunker.chunk)
39
+
40
+ chunker.reset
41
+ elsif chunker.is_complete?
42
+ yield(chunker.chunk)
43
+
44
+ break
45
+ else
46
+ chunker.add(process_row(row))
47
+ end
48
+ end
49
+ end
50
+
51
+ csv_tempfile.unlink
52
+ ftp.close
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def sanitize(data)
59
+ return data unless data.is_a?(String)
60
+ data.strip
61
+ end
62
+
63
+ def process_row(row)
64
+ {
65
+ upc: sanitize(row[1]),
66
+ item_identifier: sanitize(row[0]),
67
+ name: sanitize(row[2]),
68
+ short_description: sanitize(row[2]),
69
+ category: row[3].nil? ? row[3] : RsrGroup::Department.new(row[3]).name,
70
+ brand: sanitize(row[10]),
71
+ map_price: sanitize(row[72]),
72
+ price: sanitize(row[6]),
73
+ quantity: (Integer(sanitize(row[8])) rescue 0),
74
+ mfg_number: sanitize(row[11]),
75
+ weight: sanitize(row[7]),
76
+ long_description: sanitize(row[13]),
77
+ features: {
78
+ shipping_length: sanitize(row[74]),
79
+ shipping_width: sanitize(row[75]),
80
+ shipping_height: sanitize(row[76])
81
+ }
82
+ }
83
+ end
84
+
85
+ end
86
+ end
@@ -26,9 +26,9 @@ module RsrGroup
26
26
  @name = points[3]
27
27
  @zip = points[4]
28
28
  when :order_detail # 20
29
- get_errors(points[6]) if has_errors && points[6] != "00000"
30
- @quantity = points[3].to_i
31
- @stock_id = points[2]
29
+ get_errors(points[-1]) if has_errors && points[-1] != "00000"
30
+ @quantity = points[3].to_i
31
+ @stock_id = points[2]
32
32
  @shipping_carrier = points[4]
33
33
  @shipping_method = SHIPPING_METHODS[points[5]]
34
34
  when :confirmation_header # 30
@@ -3,281 +3,24 @@ module RsrGroup
3
3
 
4
4
  KEYDEALER_DIR = 'keydealer'.freeze
5
5
  INVENTORY_DIR = 'ftpdownloads'.freeze
6
- INVENTORY_FILENAME = 'rsrinventory-new.txt'.freeze
7
- KEYDEALER_FILENAME = 'rsrinventory-keydlr-new.txt'.freeze
8
6
  QTY_FILENAME = 'IM-QTY-CSV.csv'.freeze
9
7
  MAP_FILENAME = 'retail-map.csv'.freeze
10
8
 
11
9
  def initialize(options = {})
12
10
  requires!(options, :username, :password)
13
- @options = options
14
- end
15
-
16
- def self.all(options = {})
17
- requires!(options, :username, :password)
18
- new(options).all
19
- end
20
-
21
- def self.process_as_chunks(size = 15, options = {}, &block)
22
- requires!(options, :username, :password)
23
- new(options).process_as_chunks(size, &block)
24
- end
25
11
 
26
- def self.map_prices(options = {})
27
- requires!(options, :username, :password)
28
- new(options).map_prices
29
- end
30
-
31
- def self.map_prices_as_chunks(size = 15, options = {}, &block)
32
- requires!(options, :username, :password)
33
- new(options).map_prices_as_chunks(size, &block)
34
- end
35
-
36
- def self.quantities(options = {})
37
- requires!(options, :username, :password)
38
- new(options).quantities
12
+ @options = options
39
13
  end
40
14
 
41
- def self.quantities_as_chunks(size = 15, options = {}, &block)
15
+ def self.all(chunk_size = 15, options = {}, &block)
42
16
  requires!(options, :username, :password)
43
- new(options).quantities_as_chunks(size, &block)
44
- end
45
-
46
- def all
47
- items = []
48
-
49
- connect(@options) do |ftp|
50
- if ftp.nlst.include?(KEYDEALER_DIR)
51
- ftp.chdir(KEYDEALER_DIR)
52
- lines = ftp.gettextfile(KEYDEALER_FILENAME, nil)
53
- else
54
- ftp.chdir(INVENTORY_DIR)
55
- lines = ftp.gettextfile(INVENTORY_FILENAME, nil)
56
- end
57
-
58
- # Use a zero-byte char as `quote_char` since the data has no quote character.
59
- CSV.parse(lines, col_sep: ';', quote_char: "\x00") do |row|
60
- items << {
61
- stock_number: sanitize(row[0]),
62
- upc: sanitize(row[1]),
63
- description: sanitize(row[2]),
64
- department: row[3].nil? ? row[3] : RsrGroup::Department.new(row[3]),
65
- manufacturer_id: sanitize(row[4]),
66
- retail_price: sanitize(row[5]),
67
- regular_price: sanitize(row[6]),
68
- weight: sanitize(row[7]),
69
- quantity: (Integer(sanitize(row[8])) rescue 0),
70
- model: sanitize(row[9]),
71
- manufacturer_name: sanitize(row[10]),
72
- manufacturer_part_number: sanitize(row[11]),
73
- allocated_closeout_deleted: sanitize(row[12]),
74
- description_full: sanitize(row[13]),
75
- image_name: sanitize(row[14]),
76
- restricted_states: {
77
- AK: row[15] == 'Y',
78
- AL: row[16] == 'Y',
79
- AR: row[17] == 'Y',
80
- AZ: row[18] == 'Y',
81
- CA: row[19] == 'Y',
82
- CO: row[20] == 'Y',
83
- CT: row[21] == 'Y',
84
- DC: row[22] == 'Y',
85
- DE: row[23] == 'Y',
86
- FL: row[24] == 'Y',
87
- GA: row[25] == 'Y',
88
- HI: row[26] == 'Y',
89
- IA: row[27] == 'Y',
90
- ID: row[28] == 'Y',
91
- IL: row[29] == 'Y',
92
- IN: row[30] == 'Y',
93
- KS: row[31] == 'Y',
94
- KY: row[32] == 'Y',
95
- LA: row[33] == 'Y',
96
- MA: row[36] == 'Y',
97
- MD: row[37] == 'Y',
98
- ME: row[38] == 'Y',
99
- MI: row[39] == 'Y',
100
- MN: row[40] == 'Y',
101
- MO: row[41] == 'Y',
102
- MS: row[42] == 'Y',
103
- MT: row[43] == 'Y',
104
- NC: row[44] == 'Y',
105
- ND: row[45] == 'Y',
106
- NE: row[46] == 'Y',
107
- NH: row[47] == 'Y',
108
- NJ: row[48] == 'Y',
109
- NM: row[49] == 'Y',
110
- NV: row[50] == 'Y',
111
- NY: row[51] == 'Y',
112
- OH: row[52] == 'Y',
113
- OK: row[53] == 'Y',
114
- OR: row[54] == 'Y',
115
- PA: row[55] == 'Y',
116
- RI: row[56] == 'Y',
117
- SC: row[57] == 'Y',
118
- SD: row[58] == 'Y',
119
- TN: row[59] == 'Y',
120
- TX: row[60] == 'Y',
121
- UT: row[61] == 'Y',
122
- VA: row[62] == 'Y',
123
- VT: row[63] == 'Y',
124
- WA: row[64] == 'Y',
125
- WI: row[65] == 'Y',
126
- WV: row[66] == 'Y',
127
- WY: row[67] == 'Y',
128
- },
129
- ground_shipping_only: row[68] == 'Y',
130
- adult_signature_required: row[69] == 'Y',
131
- blocked_from_drop_ship: row[70] == 'Y',
132
- date_entered: row[71].nil? ? row[71] : Date.strptime(row[71], '%Y%m%d'),
133
- retail_map: sanitize(row[72]),
134
- image_disclaimer: row[73] == 'Y',
135
- shipping_length: sanitize(row[74]),
136
- shipping_width: sanitize(row[75]),
137
- shipping_height: sanitize(row[76]),
138
- }
139
- end
140
-
141
- ftp.close
142
- end
143
-
144
- items
145
- end
146
-
147
- def process_as_chunks(size, &block)
148
- connect(@options) do |ftp|
149
- chunker = RsrGroup::Chunker.new(size)
150
- temp_csv_file = Tempfile.new
151
-
152
- # Is this a key dealer?
153
- if ftp.nlst.include?(KEYDEALER_DIR)
154
- ftp.chdir(KEYDEALER_DIR)
155
-
156
- # Pull from the FTP and save as a temp file
157
- ftp.getbinaryfile(KEYDEALER_FILENAME, temp_csv_file.path)
158
- else
159
- ftp.chdir(INVENTORY_DIR)
160
-
161
- # Pull from the FTP and save as a temp file
162
- ftp.getbinaryfile(INVENTORY_FILENAME, temp_csv_file.path)
163
- end
164
-
165
- # total_count is the number of lines in the file
166
- chunker.total_count = File.readlines(temp_csv_file).size
167
-
168
- CSV.readlines(temp_csv_file, col_sep: ';', quote_char: "\x00").to_enum.with_index(1).each do |row, current_line|
169
-
170
- if chunker.is_full?
171
- yield(chunker.chunk)
172
-
173
- chunker.reset
174
- elsif chunker.is_complete?
175
- yield(chunker.chunk)
176
-
177
- break
178
- else
179
- chunker.add(process_row(row))
180
- end
181
- end
182
-
183
- temp_csv_file.unlink
184
- ftp.close
185
- end
186
- end
187
-
188
- def map_prices
189
- rows = []
190
-
191
- connect(@options) do |ftp|
192
- if ftp.nlst.include?(KEYDEALER_DIR)
193
- ftp.chdir(KEYDEALER_DIR)
194
- else
195
- ftp.chdir(INVENTORY_DIR)
196
- end
197
-
198
- ftp.gettextfile(MAP_FILENAME, nil) do |line|
199
- points = line.split(',').map(&:rstrip)
200
- rows << {
201
- stock_number: points[0],
202
- map_price: points[1],
203
- }
204
- end
205
-
206
- ftp.close
207
- end
208
-
209
- rows
210
- end
211
-
212
- def map_prices_as_chunks(size, &block)
213
- connect(@options) do |ftp|
214
- chunker = RsrGroup::Chunker.new(size)
215
- temp_csv_file = Tempfile.new
216
-
217
- # Is this a key dealer?
218
- if ftp.nlst.include?(KEYDEALER_DIR)
219
- ftp.chdir(KEYDEALER_DIR)
220
- else
221
- ftp.chdir(INVENTORY_DIR)
222
- end
223
-
224
- # Pull from the FTP and save as a temp file
225
- ftp.getbinaryfile(MAP_FILENAME, temp_csv_file.path)
226
-
227
- # total_count is hte number of lines in the file
228
- chunker.total_count = File.readlines(temp_csv_file).size
229
-
230
- CSV.readlines(temp_csv_file).each do |row|
231
- if chunker.is_full?
232
- yield(chunker.chunk)
233
-
234
- chunker.reset
235
- elsif chunker.is_complete?
236
- yield(chunker.chunk)
237
-
238
- break
239
- else
240
- chunker.add({
241
- stock_number: row[0].strip,
242
- map_price: row[1]
243
- })
244
- end
245
- end
246
-
247
- temp_csv_file.unlink
248
- ftp.close
249
- end
250
- end
251
-
252
- def quantities
253
- rows = []
254
-
255
- connect(@options) do |ftp|
256
- if ftp.nlst.include?(KEYDEALER_DIR)
257
- ftp.chdir(KEYDEALER_DIR)
258
- else
259
- ftp.chdir(INVENTORY_DIR)
260
- end
261
-
262
- csv = ftp.gettextfile(QTY_FILENAME, nil)
263
-
264
- CSV.parse(csv) do |row|
265
- rows << {
266
- stock_number: row[0].rstrip,
267
- quantity: row[1].to_i,
268
- }
269
- end
270
-
271
- ftp.close
272
- end
273
-
274
- rows
17
+ new(options).all(chunk_size, &block)
275
18
  end
276
19
 
277
- def quantities_as_chunks(size, &block)
20
+ def all(chunk_size, &block)
278
21
  connect(@options) do |ftp|
279
- chunker = RsrGroup::Chunker.new(size)
280
- temp_csv_file = Tempfile.new
22
+ chunker = RsrGroup::Chunker.new(chunk_size)
23
+ csv_tempfile = Tempfile.new
281
24
 
282
25
  # Is this a key dealer?
283
26
  if ftp.nlst.include?(KEYDEALER_DIR)
@@ -287,12 +30,12 @@ module RsrGroup
287
30
  end
288
31
 
289
32
  # Pull from the FTP and save as a temp file
290
- ftp.getbinaryfile(QTY_FILENAME, temp_csv_file.path)
33
+ ftp.getbinaryfile(QTY_FILENAME, csv_tempfile.path)
291
34
 
292
35
  # total_count is hte number of lines in the file
293
- chunker.total_count = File.readlines(temp_csv_file).size
36
+ chunker.total_count = File.readlines(csv_tempfile).size
294
37
 
295
- CSV.readlines(temp_csv_file).each do |row|
38
+ CSV.readlines(csv_tempfile).each do |row|
296
39
  if chunker.is_full?
297
40
  yield(chunker.chunk)
298
41
 
@@ -303,106 +46,16 @@ module RsrGroup
303
46
  break
304
47
  else
305
48
  chunker.add({
306
- stock_number: row[0].rstrip,
307
- quantity: row[1].to_i
49
+ item_identifier: row[0].rstrip,
50
+ quantity: row[1].to_i
308
51
  })
309
52
  end
310
53
  end
311
54
 
312
- temp_csv_file.unlink
55
+ csv_tempfile.unlink
313
56
  ftp.close
314
57
  end
315
58
  end
316
59
 
317
-
318
- private
319
-
320
- def sanitize(data)
321
- return data unless data.is_a?(String)
322
- data.strip
323
- end
324
-
325
- def process_row(row)
326
- {
327
- stock_number: sanitize(row[0]),
328
- upc: sanitize(row[1]),
329
- description: sanitize(row[2]),
330
- department: row[3].nil? ? row[3] : RsrGroup::Department.new(row[3]),
331
- manufacturer_id: sanitize(row[4]),
332
- retail_price: sanitize(row[5]),
333
- regular_price: sanitize(row[6]),
334
- weight: sanitize(row[7]),
335
- quantity: (Integer(sanitize(row[8])) rescue 0),
336
- model: sanitize(row[9]),
337
- manufacturer_name: sanitize(row[10]),
338
- manufacturer_part_number: sanitize(row[11]),
339
- allocated_closeout_deleted: sanitize(row[12]),
340
- description_full: sanitize(row[13]),
341
- image_name: sanitize(row[14]),
342
- restricted_states: {
343
- AK: row[15] == 'Y',
344
- AL: row[16] == 'Y',
345
- AR: row[17] == 'Y',
346
- AZ: row[18] == 'Y',
347
- CA: row[19] == 'Y',
348
- CO: row[20] == 'Y',
349
- CT: row[21] == 'Y',
350
- DC: row[22] == 'Y',
351
- DE: row[23] == 'Y',
352
- FL: row[24] == 'Y',
353
- GA: row[25] == 'Y',
354
- HI: row[26] == 'Y',
355
- IA: row[27] == 'Y',
356
- ID: row[28] == 'Y',
357
- IL: row[29] == 'Y',
358
- IN: row[30] == 'Y',
359
- KS: row[31] == 'Y',
360
- KY: row[32] == 'Y',
361
- LA: row[33] == 'Y',
362
- MA: row[36] == 'Y',
363
- MD: row[37] == 'Y',
364
- ME: row[38] == 'Y',
365
- MI: row[39] == 'Y',
366
- MN: row[40] == 'Y',
367
- MO: row[41] == 'Y',
368
- MS: row[42] == 'Y',
369
- MT: row[43] == 'Y',
370
- NC: row[44] == 'Y',
371
- ND: row[45] == 'Y',
372
- NE: row[46] == 'Y',
373
- NH: row[47] == 'Y',
374
- NJ: row[48] == 'Y',
375
- NM: row[49] == 'Y',
376
- NV: row[50] == 'Y',
377
- NY: row[51] == 'Y',
378
- OH: row[52] == 'Y',
379
- OK: row[53] == 'Y',
380
- OR: row[54] == 'Y',
381
- PA: row[55] == 'Y',
382
- RI: row[56] == 'Y',
383
- SC: row[57] == 'Y',
384
- SD: row[58] == 'Y',
385
- TN: row[59] == 'Y',
386
- TX: row[60] == 'Y',
387
- UT: row[61] == 'Y',
388
- VA: row[62] == 'Y',
389
- VT: row[63] == 'Y',
390
- WA: row[64] == 'Y',
391
- WI: row[65] == 'Y',
392
- WV: row[66] == 'Y',
393
- WY: row[67] == 'Y',
394
- },
395
- ground_shipping_only: row[68] == 'Y',
396
- adult_signature_required: row[69] == 'Y',
397
- blocked_from_drop_ship: row[70] == 'Y',
398
- date_entered: row[71].nil? ? row[71] : Date.strptime(row[71], '%Y%m%d'),
399
- retail_map: sanitize(row[72]),
400
- image_disclaimer: row[73] == 'Y',
401
- shipping_length: sanitize(row[74]),
402
- shipping_width: sanitize(row[75]),
403
- shipping_height: sanitize(row[76]),
404
- }
405
- end
406
-
407
60
  end
408
61
  end
@@ -7,17 +7,6 @@ module RsrGroup
7
7
  # * Call {#submit!} to send the order
8
8
  class Order < Base
9
9
 
10
- class ResponseStruct < Struct.new(:success, :message, :data)
11
-
12
- # Simple response object to pass along success/falure/messages of any process
13
- # Usage:
14
- # response = ResponseStruct.new(true)
15
- # response = ResponseStruct.new(false, "You did the wrong thing")
16
- # response = ResponseStruct.new(true, nil, { result: 200 })
17
-
18
- alias success? success
19
- end
20
-
21
10
  # @param [Hash] options
22
11
  # @option options [String] :merchant_number *required*
23
12
  # @option options [Integer] :sequence_number *required*
@@ -98,16 +87,12 @@ module RsrGroup
98
87
  io = StringIO.new(to_txt)
99
88
  begin
100
89
  ftp.storlines("STOR " + filename, io)
101
- success = ftp.nlst.include?(filename)
102
- @response = ResponseStruct.new(success, nil, modified: ftp.mtime(filename), size: ftp.size(filename))
103
90
  ensure
104
91
  io.close
105
92
  end
106
93
  ftp.close
107
94
  end
108
- @response || ResponseStruct.new(false)
109
- rescue Net::FTPPermError => e
110
- return ResponseStruct.new(false, e.message.chomp)
95
+ true
111
96
  end
112
97
 
113
98
  private
@@ -1,3 +1,3 @@
1
1
  module RsrGroup
2
- VERSION = '1.8.0'.freeze
2
+ VERSION = '2.0.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rsr_group
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Campbell
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-04-23 00:00:00.000000000 Z
11
+ date: 2017-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: smarter_csv
@@ -101,6 +101,7 @@ files:
101
101
  - config.rb.example
102
102
  - lib/rsr_group.rb
103
103
  - lib/rsr_group/base.rb
104
+ - lib/rsr_group/catalog.rb
104
105
  - lib/rsr_group/chunker.rb
105
106
  - lib/rsr_group/constants.rb
106
107
  - lib/rsr_group/data_row.rb
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  version: '0'
135
136
  requirements: []
136
137
  rubyforge_project:
137
- rubygems_version: 2.6.12
138
+ rubygems_version: 2.5.1
138
139
  signing_key:
139
140
  specification_version: 4
140
141
  summary: RSR Group Ruby library