davidsons 1.0.4 → 3.0.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/lib/davidsons/base.rb +3 -11
- data/lib/davidsons/catalog.rb +50 -25
- data/lib/davidsons/inventory.rb +85 -50
- data/lib/davidsons/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b286e3483e84a4b0fd324fadb43e51d780a38127d34bb0bc75ff7cfb9f33d67d
|
4
|
+
data.tar.gz: 8abfaf696c4b51cea85a4683abfc29e941ab57d6a63467498bc59d269b553010
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b2c54f5e13281b8ef373ff67ccda709c279ed583420845f1fa4f9477a5153fad8df0524a19181a5974315b3dd06db1a63c1a91c3996503abc974c09f7e2460a
|
7
|
+
data.tar.gz: 271fba58c6784f8b014aa9de3f5e7f58a78f0962aacc420326209cb7d31f70e6fb24da3b23d27502b841d3a8cf0c73c7e77775a4b03a571bb2771b738f73361e
|
data/.gitignore
CHANGED
data/lib/davidsons/base.rb
CHANGED
@@ -47,17 +47,9 @@ module Davidsons
|
|
47
47
|
|
48
48
|
def get_file(filename)
|
49
49
|
connect(@options) do |ftp|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
ftp.getbinaryfile(filename, tempfile.path)
|
54
|
-
|
55
|
-
tempfile.close
|
56
|
-
|
57
|
-
tempfile
|
58
|
-
ensure
|
59
|
-
ftp.close
|
60
|
-
end
|
50
|
+
tempfile = Tempfile.new
|
51
|
+
ftp.getbinaryfile(filename, tempfile.path)
|
52
|
+
tempfile
|
61
53
|
end
|
62
54
|
end
|
63
55
|
|
data/lib/davidsons/catalog.rb
CHANGED
@@ -1,13 +1,31 @@
|
|
1
1
|
module Davidsons
|
2
2
|
class Catalog < Base
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
WHOLE_CATALOG_FILENAME = 'davidsons_inventory.csv'.freeze
|
5
|
+
DEFAULT_SMART_OPTS = {
|
6
|
+
chunk_size: 500,
|
7
|
+
convert_values_to_numeric: false,
|
8
|
+
force_utf8: true,
|
9
|
+
key_mapping: {
|
10
|
+
"item_#": :item_identifier,
|
11
|
+
item_description: :name,
|
12
|
+
upc_code: :upc,
|
13
|
+
manufacturer: :brand,
|
14
|
+
retail_price: :msrp,
|
15
|
+
gun_type: :category,
|
16
|
+
}
|
17
|
+
}
|
6
18
|
|
19
|
+
# @param [Hash] options
|
20
|
+
# @option options [Symbol] :username *required*
|
21
|
+
# @option options [Symbol] :password *required*
|
22
|
+
# @option options [Symbol] :pricing_tier *optional*
|
23
|
+
# * Denotes which price to use
|
24
|
+
# * Can be :regular or :minimum
|
7
25
|
def initialize(options = {})
|
8
26
|
requires!(options, :username, :password)
|
9
|
-
|
10
27
|
@options = options
|
28
|
+
@options[:pricing_tier] ||= :regular
|
11
29
|
end
|
12
30
|
|
13
31
|
def self.all(options = {}, &block)
|
@@ -16,42 +34,48 @@ module Davidsons
|
|
16
34
|
end
|
17
35
|
|
18
36
|
def all(&block)
|
19
|
-
tempfile = get_file(
|
20
|
-
|
21
|
-
# TODO: account for Sale Price and MSP (minimum price)
|
37
|
+
tempfile = get_file(WHOLE_CATALOG_FILENAME)
|
22
38
|
|
23
|
-
SmarterCSV.process(tempfile
|
24
|
-
chunk_size: CHUNK_SIZE,
|
25
|
-
convert_values_to_numeric: false,
|
26
|
-
force_utf8: true,
|
27
|
-
key_mapping: {
|
28
|
-
"item_#": :item_identifier,
|
29
|
-
item_description: :name,
|
30
|
-
upc_code: :upc,
|
31
|
-
manufacturer: :brand,
|
32
|
-
retail_price: :msrp,
|
33
|
-
dealer_price: :price,
|
34
|
-
gun_type: :category,
|
35
|
-
}
|
36
|
-
}) do |chunk|
|
39
|
+
SmarterCSV.process(tempfile, DEFAULT_SMART_OPTS) do |chunk|
|
37
40
|
chunk.each do |item|
|
38
|
-
item.except!(:retail_price, :capacity, :sale_price, :sale_ends)
|
39
|
-
|
40
41
|
item[:msrp].tr!('$', '')
|
41
|
-
item[:price].tr!('$', '')
|
42
42
|
item[:upc].tr!('#', '')
|
43
43
|
|
44
|
+
item[:price] = lowest_price(item)
|
44
45
|
item[:mfg_number] = item[:item_identifier]
|
45
|
-
item[:quantity]
|
46
|
-
item[:features]
|
46
|
+
item[:quantity] = item[:quantity].to_i
|
47
|
+
item[:features] = map_features(item)
|
48
|
+
|
49
|
+
item.delete(:sale_ends)
|
50
|
+
item.delete(:sale_price)
|
47
51
|
|
48
52
|
yield(item)
|
49
53
|
end
|
50
54
|
end
|
55
|
+
|
56
|
+
tempfile.unlink
|
51
57
|
end
|
52
58
|
|
53
59
|
protected
|
54
60
|
|
61
|
+
def lowest_price(item)
|
62
|
+
case @options[:pricing_tier]
|
63
|
+
when :minimum
|
64
|
+
relevant_price = item.delete(:msp).tr('$', '')
|
65
|
+
item.delete(:dealer_price)
|
66
|
+
else
|
67
|
+
relevant_price = item.delete(:dealer_price).tr('$', '')
|
68
|
+
item.delete(:msp)
|
69
|
+
end
|
70
|
+
|
71
|
+
if item[:sale_price]
|
72
|
+
sale_price = item.delete(:sale_price).tr('$', '')
|
73
|
+
return sale_price if sale_price.to_f < relevant_price.to_f
|
74
|
+
end
|
75
|
+
|
76
|
+
relevant_price
|
77
|
+
end
|
78
|
+
|
55
79
|
def map_features(item)
|
56
80
|
{
|
57
81
|
finish: item.delete(:finish),
|
@@ -60,6 +84,7 @@ module Davidsons
|
|
60
84
|
model_series: item.delete(:model_series),
|
61
85
|
sights: item.delete(:sights),
|
62
86
|
stock: item.delete(:stock),
|
87
|
+
capacity: item.delete(:capacity),
|
63
88
|
}
|
64
89
|
end
|
65
90
|
|
data/lib/davidsons/inventory.rb
CHANGED
@@ -1,89 +1,124 @@
|
|
1
1
|
module Davidsons
|
2
2
|
class Inventory < Base
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
WHOLE_CATALOG_FILENAME = 'davidsons_inventory.csv'.freeze
|
5
|
+
DEFAULT_WHOLE_CATALOG_SMART_OPTS = {
|
6
|
+
chunk_size: 500,
|
7
|
+
convert_values_to_numeric: false,
|
8
|
+
force_utf8: true,
|
9
|
+
remove_unmapped_keys: true,
|
10
|
+
key_mapping: {
|
11
|
+
"item_#": :item_identifier,
|
12
|
+
upc_code: :upc,
|
13
|
+
msp: :msp,
|
14
|
+
dealer_price: :dealer_price,
|
15
|
+
sale_price: :sale_price,
|
16
|
+
quantity: :quantity,
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
QUANTITY_FILENAME = 'davidsons_quantity.csv'.freeze
|
21
|
+
DEFAULT_QUANTITY_SMART_OPTS = {
|
22
|
+
chunk_size: 2000,
|
23
|
+
convert_values_to_numeric: false,
|
24
|
+
force_utf8: true,
|
25
|
+
key_mapping: {
|
26
|
+
item_number: :item_identifier,
|
27
|
+
upc_code: :upc
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
# @param [Hash] options
|
32
|
+
# @option options [Symbol] :username *required*
|
33
|
+
# @option options [Symbol] :password *required*
|
34
|
+
# @option options [Symbol] :pricing_tier *optional*
|
35
|
+
# * Denotes which price to use
|
36
|
+
# * Can be :regular or :minimum
|
7
37
|
def initialize(options = {})
|
8
38
|
requires!(options, :username, :password)
|
9
|
-
|
10
39
|
@options = options
|
40
|
+
@options[:pricing_tier] ||= :regular
|
11
41
|
end
|
12
42
|
|
43
|
+
# Iterates over all items in the 'davidsons_inventory.csv' file yielding the item_identifier, quantity, and price.
|
44
|
+
# We have to use this file since the 'davidsons_quantity.csv' file does not included prices.
|
45
|
+
# The price can vary based on the +pricing_tier+
|
46
|
+
#
|
47
|
+
# @param [Hash] options
|
48
|
+
# @option options [Symbol] :username *required*
|
49
|
+
# @option options [Symbol] :password *required*
|
50
|
+
# @option options [Symbol] :pricing_tier *optional*
|
51
|
+
# * Denotes which price to use
|
52
|
+
# * Can be :regular or :minimum
|
13
53
|
def self.all(options = {}, &block)
|
14
54
|
requires!(options, :username, :password)
|
15
|
-
new(options).
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.get_quantity_file(options = {})
|
19
|
-
requires!(options, :username, :password)
|
20
|
-
new(options).get_quantity_file
|
55
|
+
new(options).all(&block)
|
21
56
|
end
|
22
57
|
|
58
|
+
# Iterates over all items in the 'davidsons_quantity.csv' file yielding the item_identifier, upc, quantity and locations.
|
59
|
+
#
|
60
|
+
# @param [Hash] options
|
61
|
+
# @option options [Symbol] :username *required*
|
62
|
+
# @option options [Symbol] :password *required*
|
23
63
|
def self.quantity(options = {}, &block)
|
24
64
|
requires!(options, :username, :password)
|
25
65
|
new(options).quantity(&block)
|
26
66
|
end
|
27
67
|
|
28
|
-
def
|
29
|
-
tempfile = get_file(
|
30
|
-
|
31
|
-
SmarterCSV.process(tempfile.open, {
|
32
|
-
chunk_size: CHUNK_SIZE,
|
33
|
-
convert_values_to_numeric: false,
|
34
|
-
force_utf8: true,
|
35
|
-
key_mapping: { item_number: :item_identifier }
|
36
|
-
}) do |chunk|
|
37
|
-
chunk.each do |item|
|
38
|
-
item.except!(:upc_code)
|
68
|
+
def all
|
69
|
+
tempfile = get_file(WHOLE_CATALOG_FILENAME)
|
39
70
|
|
40
|
-
|
41
|
-
|
71
|
+
SmarterCSV.process(tempfile, DEFAULT_WHOLE_CATALOG_SMART_OPTS) do |chunk|
|
72
|
+
chunk.each do |item|
|
73
|
+
item[:upc].tr!('#', '')
|
42
74
|
|
43
|
-
item
|
75
|
+
item[:price] = lowest_price(item)
|
76
|
+
item[:quantity] = item[:quantity].to_i
|
44
77
|
|
45
78
|
yield(item)
|
46
79
|
end
|
47
80
|
end
|
48
81
|
end
|
49
82
|
|
50
|
-
def
|
51
|
-
|
52
|
-
tempfile = Tempfile.new
|
53
|
-
|
54
|
-
SmarterCSV.process(inventory_tempfile.open, {
|
55
|
-
chunk_size: CHUNK_SIZE,
|
56
|
-
convert_values_to_numeric: false,
|
57
|
-
force_utf8: true,
|
58
|
-
key_mapping: {
|
59
|
-
item_number: :item_identifier
|
60
|
-
}
|
61
|
-
}) do |chunk|
|
62
|
-
chunk.each do |item|
|
63
|
-
item.except!(:upc_code)
|
64
|
-
|
65
|
-
item[:quantity] = item[:quantity_nc].to_i + item[:quantity_az].to_i
|
83
|
+
def quantity(&block)
|
84
|
+
tempfile = get_file(QUANTITY_FILENAME)
|
66
85
|
|
67
|
-
|
86
|
+
SmarterCSV.process(tempfile, DEFAULT_QUANTITY_SMART_OPTS) do |chunk|
|
87
|
+
chunk.each do |item|
|
88
|
+
item[:quantity] = item[:quantity_nc].to_i + item[:quantity_az].to_i
|
89
|
+
item[:locations] = map_location_quantities(item)
|
68
90
|
|
69
|
-
|
91
|
+
yield(item)
|
70
92
|
end
|
71
93
|
end
|
72
|
-
|
73
|
-
inventory_tempfile.unlink
|
74
|
-
tempfile.close
|
75
|
-
|
76
|
-
tempfile.path
|
77
94
|
end
|
78
95
|
|
79
|
-
|
96
|
+
private
|
80
97
|
|
81
98
|
def map_location_quantities(item)
|
82
99
|
{
|
83
|
-
nc: item
|
84
|
-
az: item
|
100
|
+
nc: item.delete(:quantity_nc),
|
101
|
+
az: item.delete(:quantity_az),
|
85
102
|
}
|
86
103
|
end
|
87
104
|
|
105
|
+
def lowest_price(item)
|
106
|
+
case @options[:pricing_tier]
|
107
|
+
when :minimum
|
108
|
+
relevant_price = item.delete(:msp).tr('$', '')
|
109
|
+
item.delete(:dealer_price)
|
110
|
+
else
|
111
|
+
relevant_price = item.delete(:dealer_price).tr('$', '')
|
112
|
+
item.delete(:msp)
|
113
|
+
end
|
114
|
+
|
115
|
+
if item[:sale_price]
|
116
|
+
sale_price = item.delete(:sale_price).tr('$', '')
|
117
|
+
return sale_price if sale_price.to_f < relevant_price.to_f
|
118
|
+
end
|
119
|
+
|
120
|
+
relevant_price
|
121
|
+
end
|
122
|
+
|
88
123
|
end
|
89
124
|
end
|
data/lib/davidsons/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: davidsons
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0.pre2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Knight
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-09-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: savon
|
@@ -136,9 +136,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
136
136
|
version: '0'
|
137
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
|
-
- - "
|
139
|
+
- - ">"
|
140
140
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
141
|
+
version: 1.3.1
|
142
142
|
requirements: []
|
143
143
|
rubyforge_project:
|
144
144
|
rubygems_version: 2.7.7
|