peddler 0.7.5 → 0.7.6

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: 5537d0a71a142b77a5d4e7c75f28782ccaa61174
4
- data.tar.gz: bb52e6a9cb17b2eef6eead010d236d0c4c47f619
3
+ metadata.gz: f9b31544fe3d9183ca13cfaf52fc46b17b63bd7c
4
+ data.tar.gz: 812917ae3a325ea06882348325ac001057bc3335
5
5
  SHA512:
6
- metadata.gz: 3f4d91eeab8827b397da404a9d7be300adf8ee2180613bfbc19a23ce4c048c3a2b8a2adc0b571bbb562dac860de9b1114ac143d53203c0077407122c58bece1f
7
- data.tar.gz: 2cd754fe9a2e94dd71dc61c98ac3afeb41b552370d51ce5ef2ffcb6c3b3a87412ddc7b14c4e66540a125c0b5b8752fe9bf8d3c7143bf47114325d7c619985e84
6
+ metadata.gz: 2cd7197ad9e27655e0f6c0554c12e2e703a9687e90d086d3330b76886bb30ac017e025e9f3ab328b2eb2098e2a0abb42492c35c9a4937f9174d92a3f93bc6cd6
7
+ data.tar.gz: 140a6b3e7091da63b3a42507749841803b10f1e215c956a9003f2f305126ff1335d60c107de305e15931b167a2fd5448bb444106d60b1bcb920db0a4f5b2615f
data/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  [![Build Status][1]][2]
4
4
 
5
- ![Peddler][3]
6
-
7
- **Peddler** is a Ruby interface to the [Amazon MWS API][4], a collection of web services that help Amazon sellers programmatically exchange data on their listings, orders, payments, reports, and more.
5
+ **Peddler** is a Ruby interface to the [Amazon MWS API][3], a collection of web services that help Amazon sellers programmatically exchange data on their listings, orders, payments, reports, and more.
8
6
 
9
7
  To use Amazon MWS, you must have an eligible seller account.
10
8
 
9
+ ![Peddler][4]
10
+
11
11
  ## Configuration
12
12
 
13
13
  Require the entire library or a particular API section.
@@ -131,5 +131,5 @@ The Amazon MWS Subscriptions API section enables you to subscribe to receive not
131
131
 
132
132
  [1]: https://travis-ci.org/hakanensari/peddler.png
133
133
  [2]:https://travis-ci.org/hakanensari/peddler
134
- [3]: http://f.cl.ly/items/231z2m0r1Q2o2q1n0w1N/peddler.jpg
135
- [4]: https://developer.amazonservices.com/
134
+ [3]: https://developer.amazonservices.com/
135
+ [4]: http://f.cl.ly/items/231z2m0r1Q2o2q1n0w1N/peddler.jpg
@@ -9,5 +9,89 @@ module MWS
9
9
  # @todo Not implemented
10
10
  class FulfillmentInboundShipment < ::Peddler::Client
11
11
  path '/FulfillmentInboundShipment/2010-10-01'
12
+
13
+ # Returns the information required to create an inbound shipment
14
+ def create_inbound_shipment_plan
15
+ raise NotImplementedError
16
+ end
17
+
18
+ # Creates an inbound shipment
19
+ def create_inbound_shipment
20
+ raise NotImplementedError
21
+ end
22
+
23
+ # Updates an existing inbound shipment
24
+ def update_inbound_shipment
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # Sends transportation information to Amazon about an inbound shipment
29
+ def put_transport_content
30
+ raise NotImplementedError
31
+ end
32
+
33
+ # Requests an estimate of the shipping cost for an inbound shipment
34
+ def estimate_transport_request
35
+ raise NotImplementedError
36
+ end
37
+
38
+ # Confirms that you accept the Amazon-partnered shipping estimate and you
39
+ # request that the Amazon-partnered carrier ship your inbound shipment
40
+ def confirm_transport_request
41
+ raise NotImplementedError
42
+ end
43
+
44
+ # Returns current transportation information about an inbound shipment
45
+ def get_transport_content
46
+ raise NotImplementedError
47
+ end
48
+
49
+ # Voids a previously-confirmed request to ship your inbound shipment using
50
+ # an Amazon-partnered carrier
51
+ def void_transport_request
52
+ raise NotImplementedError
53
+ end
54
+
55
+ # Returns PDF document data for printing package labels for an inbound
56
+ # shipment
57
+ def get_package_labels
58
+ raise NotImplementedError
59
+ end
60
+
61
+ # Returns PDF document data for printing a bill of lading for an inbound
62
+ # shipment
63
+ def get_bill_of_lading
64
+ raise NotImplementedError
65
+ end
66
+
67
+ # Returns a list of inbound shipments based on criteria that you specify
68
+ def list_inbound_shipments
69
+ raise NotImplementedError
70
+ end
71
+
72
+ # Returns the next page of inbound shipments
73
+ def list_inbound_shipments_by_next_token
74
+ raise NotImplementedError
75
+ end
76
+
77
+ # Returns a list of items in a specified inbound shipment, or a list of
78
+ # items that were updated within a specified time frame
79
+ def list_inbound_shipment_items
80
+ raise NotImplementedError
81
+ end
82
+
83
+ # Returns the next page of inbound shipment items
84
+ def list_inbound_shipment_items_by_next_token
85
+ raise NotImplementedError
86
+ end
87
+
88
+ # Gets the operational status of the API
89
+ #
90
+ # @see http://docs.developer.amazonservices.com/en_US/fba_inbound/MWS_GetServiceStatus.html
91
+ # @return [Peddler::XMLParser]
92
+ def get_service_status
93
+ operation('GetServiceStatus')
94
+ run
95
+ end
12
96
  end
13
97
  end
@@ -11,5 +11,25 @@ module MWS
11
11
  # @todo Not implemented
12
12
  class FulfillmentInventory < ::Peddler::Client
13
13
  path '/FulfillmentInventory/2010-10-01'
14
+
15
+ # Returns information about the availability of a seller's inventory
16
+ def list_inventory_supply
17
+ raise NotImplementedError
18
+ end
19
+
20
+ # Returns the next page of information about the availability of a seller's
21
+ # inventory
22
+ def list_inventory_supply_by_next_token
23
+ raise NotImplementedError
24
+ end
25
+
26
+ # Gets the operational status of the API
27
+ #
28
+ # @see http://docs.developer.amazonservices.com/en_US/fba_inventory/MWS_GetServiceStatus.html
29
+ # @return [Peddler::XMLParser]
30
+ def get_service_status
31
+ operation('GetServiceStatus')
32
+ run
33
+ end
14
34
  end
15
35
  end
@@ -13,5 +13,58 @@ module MWS
13
13
  # @todo Not implemented
14
14
  class FulfillmentOutboundShipment < ::Peddler::Client
15
15
  path '/FulfillmentOutboundShipment/2010-10-01'
16
+
17
+ # Lists fulfillment order previews
18
+ def get_fulfillment_preview
19
+ raise NotImplementedError
20
+ end
21
+
22
+ # Requests that Amazon ship items from the seller's Amazon Fulfillment
23
+ # Network inventory to a destination address
24
+ def create_fulfillment_order
25
+ raise NotImplementedError
26
+ end
27
+
28
+ # Updates and/or requests shipment for a fulfillment order with an order
29
+ # hold on it
30
+ def update_fulfillment_order
31
+ raise NotImplementedError
32
+ end
33
+
34
+ # Gets a fulfillment order
35
+ def get_fulfillment_order
36
+ raise NotImplementedError
37
+ end
38
+
39
+ # Returns a list of fulfillment orders fulfilled on or after a date
40
+ def list_all_fulfillment_orders
41
+ raise NotImplementedError
42
+ end
43
+
44
+ # Returns the next page of fulfillment orders
45
+ def list_all_fulfillment_orders_by_next_token
46
+ raise NotImplementedError
47
+ end
48
+
49
+ # Returns delivery tracking information for a package in an outbound
50
+ # shipment for a Multi-Channel Fulfillment order
51
+ def get_package_tracking_details
52
+ raise NotImplementedError
53
+ end
54
+
55
+ # Requests that Amazon stop attempting to fulfill an existing fulfillment
56
+ # order
57
+ def cancel_fulfillment_order
58
+ raise NotImplementedError
59
+ end
60
+
61
+ # Gets the operational status of the API
62
+ #
63
+ # @see http://docs.developer.amazonservices.com/en_US/fba_outbound/MWS_GetServiceStatus.html
64
+ # @return [Peddler::XMLParser]
65
+ def get_service_status
66
+ operation('GetServiceStatus')
67
+ run
68
+ end
16
69
  end
17
70
  end
@@ -211,7 +211,7 @@ module MWS
211
211
  run
212
212
  end
213
213
 
214
- # Returns the operational status of the API
214
+ # Gets the operational status of the API
215
215
  #
216
216
  # @see http://docs.developer.amazonservices.com/en_US/off_amazon_payments/OffAmazonPayments_GetServiceStatus.html
217
217
  # @return [Peddler::XMLParser]
@@ -68,7 +68,7 @@ module Peddler
68
68
  opts.store(:response_block, blk) if block_given?
69
69
  res = post(opts)
70
70
 
71
- parser.parse(res)
71
+ parser.parse(res, host_encoding)
72
72
  end
73
73
 
74
74
  private
@@ -83,6 +83,8 @@ module Peddler
83
83
 
84
84
  def host_encoding
85
85
  if host.end_with?('jp')
86
+ # Caveat: I've had one instance in the past where Shift_JIS didn't
87
+ # work but Windows-31J did when parsing a report.
86
88
  'Shift_JIS'
87
89
  elsif host.end_with?('cn')
88
90
  'UTF-16'
@@ -0,0 +1,53 @@
1
+ require 'delegate'
2
+ require 'csv'
3
+ require 'digest/md5'
4
+
5
+ module Peddler
6
+ # @api private
7
+ class FlatFileParser < SimpleDelegator
8
+ # http://stackoverflow.com/questions/8073920/importing-csv-quoting-error-is-driving-me-nuts
9
+ OPTIONS = { col_sep: "\t", quote_char: "\x00", headers: true }
10
+
11
+ attr_reader :content, :summary, :encoding
12
+
13
+ def initialize(res, encoding)
14
+ super(res)
15
+ @encoding = encoding
16
+ extract_content
17
+ end
18
+
19
+ def parse
20
+ CSV.parse(scrub_content, OPTIONS) if content
21
+ end
22
+
23
+ def records_count
24
+ summarize if summary
25
+ end
26
+
27
+ def valid?
28
+ headers['Content-MD5'] == Digest::MD5.base64digest(body)
29
+ end
30
+
31
+ private
32
+
33
+ def extract_content
34
+ if has_summary?
35
+ @summary, @content = body.split("\n\n")
36
+ else
37
+ @content = body.dup
38
+ end
39
+ end
40
+
41
+ def scrub_content
42
+ content.force_encoding(encoding).encode('UTF-8')
43
+ end
44
+
45
+ def has_summary?
46
+ body.start_with?('Feed Processing Summary')
47
+ end
48
+
49
+ def summarize
50
+ Hash[summary.split("\n\t")[1, 2].map { |line| line.split("\t\t") }]
51
+ end
52
+ end
53
+ end
@@ -1,20 +1,24 @@
1
- require 'peddler/csv_parser'
1
+ require 'peddler/flat_file_parser'
2
2
  require 'peddler/xml_parser'
3
3
 
4
4
  module Peddler
5
5
  # @api private
6
6
  module Parser
7
- def self.parse(res)
8
- # Don't parse if there's no body
9
- return res unless res.body
7
+ class << self
8
+ # The inevitable messiness of massaging data produced by a motley army of
9
+ # Amazon developers
10
+ def parse(res, encoding = 'ISO-8859-1')
11
+ # Don't parse if there's no body
12
+ return res unless res.body
10
13
 
11
- case res.headers['Content-Type']
12
- when 'text/xml'
13
- XMLParser.new(res)
14
- when 'application/octet-stream'
15
- CSVParser.new(res)
16
- else
17
- raise NotImplementedError
14
+ case res.headers['Content-Type']
15
+ when 'text/xml'
16
+ XMLParser.new(res)
17
+ when 'application/octet-stream'
18
+ FlatFileParser.new(res, encoding)
19
+ else
20
+ raise NotImplementedError
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -1,3 +1,3 @@
1
1
  module Peddler
2
- VERSION = '0.7.5'
2
+ VERSION = '0.7.6'
3
3
  end
@@ -0,0 +1,11 @@
1
+ require 'integration_helper'
2
+ require 'mws/fulfillment_inbound_shipment'
3
+
4
+ class FulfillmentInboundShipmentTest < IntegrationTest
5
+ def test_gets_service_status
6
+ clients.each do |client|
7
+ res = client.get_service_status
8
+ refute_empty res.parse
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'integration_helper'
2
+ require 'mws/fulfillment_inventory'
3
+
4
+ class FulfillmentInventoryTest < IntegrationTest
5
+ def test_gets_service_status
6
+ clients.each do |client|
7
+ res = client.get_service_status
8
+ refute_empty res.parse
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'integration_helper'
2
+ require 'mws/fulfillment_outbound_shipment'
3
+
4
+ class FulfillmentOutboundShipmentTest < IntegrationTest
5
+ def test_gets_service_status
6
+ clients.each do |client|
7
+ res = client.get_service_status
8
+ refute_empty res.parse
9
+ end
10
+ end
11
+ end
@@ -4,7 +4,7 @@ require 'peddler/client'
4
4
 
5
5
  class ClientTest < MiniTest::Test
6
6
  module Parser
7
- def self.parse(res); res; end
7
+ def self.parse(res, *); res; end
8
8
  end
9
9
 
10
10
  def setup
@@ -1,13 +1,14 @@
1
1
  require 'helper'
2
- require 'peddler/parser'
2
+ require 'peddler/flat_file_parser'
3
3
 
4
- class CSVParserTest < MiniTest::Test
4
+ class FlatFileParserTest < MiniTest::Test
5
5
  def setup
6
6
  body = "Feed Processing Summary:\n\tNumber of records processed\t\t11006\n\tNumber of records successful\t\t11006\n\noriginal-record-number\tsku\terror-code\terror-type\terror-message\n1822\t85da472e-ba6c-11e3-95af-002590a74356\t5000\tWarning\tThe update for Sku '85da472e-ba6c-11e3-95af-002590a74356' was skipped because it is identical to the update in feed '9518995390'.\n"
7
+ body.encode!('ASCII-8BIT')
7
8
  headers = { 'Content-Type' => 'application/octet-stream', 'Content-MD5' => 'SmZIMTs2mCO8u8QzR5LE7Q==' }
8
9
  res = OpenStruct.new(body: body, headers: headers)
9
10
 
10
- @parser = Peddler::Parser.parse(res)
11
+ @parser = Peddler::FlatFileParser.new(res, 'ISO-8859-1')
11
12
  end
12
13
 
13
14
  def test_parses_data
@@ -21,4 +22,21 @@ class CSVParserTest < MiniTest::Test
21
22
  def test_validates
22
23
  assert @parser.valid?
23
24
  end
25
+
26
+ def test_handles_reports_without_a_summary
27
+ res = OpenStruct.new(body: "Foo\nBar\n")
28
+ parser = Peddler::FlatFileParser.new(res, 'ISO-8859-1')
29
+
30
+ refute_empty parser.content
31
+ end
32
+
33
+ def test_handles_japanese_flat_files
34
+ body = "Foo\nこんにちは\n"
35
+ body.encode!('SHIFT_JIS')
36
+ body.force_encoding('ASCII-8BIT')
37
+ res = OpenStruct.new(body: body)
38
+ parser = Peddler::FlatFileParser.new(res, 'SHIFT_JIS')
39
+
40
+ assert_equal 'こんにちは', parser.parse[0]['Foo']
41
+ end
24
42
  end
@@ -1,12 +1,12 @@
1
1
  require 'helper'
2
- require 'peddler/parser'
2
+ require 'peddler/xml_parser'
3
3
 
4
4
  class XMLParserTest < MiniTest::Test
5
5
  def setup
6
6
  body = '<Response><Result><NextToken>123</NextToken><Foo>Bar</Foo></Result></Response>'
7
7
  res = OpenStruct.new(body: body, headers: { 'Content-Type' => 'text/xml'})
8
8
 
9
- @parser = Peddler::Parser.parse(res)
9
+ @parser = Peddler::XMLParser.new(res)
10
10
  end
11
11
 
12
12
  def test_parses_data