russianpost 0.3.0 → 0.3.1

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
  SHA1:
3
- metadata.gz: 90c9d9530331f51349587f14084ab6b1c28aa140
4
- data.tar.gz: 674b6c39bcd65a111a059e02f1a722bd7260d897
3
+ metadata.gz: f25804582583d50312fcdabb61739ab523bb1a60
4
+ data.tar.gz: d884f42475e9c64231dc79608027d8378c71a3ec
5
5
  SHA512:
6
- metadata.gz: 970d71fef77c20e95749f1edd22e6b583d2beaa6708f868320500c918d7f915d47da8bb580d5aacb03e78ea22a781de3a78b9aa43e52b049d26c7b89b5389ece
7
- data.tar.gz: 966878c1fd633dece8e1edf8287c1a3fc5cefb6757d4fa6cafceafddbf58e6f369927011d830e1ea519eff6a72934bfa4636b5a53e7ba9794a854ce541b29761
6
+ metadata.gz: 423ce97c42a91b2f8f964d80457e98b1bd8287ea6af8c8f6aadcb962ca1e9cce25ac995dd270b0253dfc69f00995fe044369145222d4a265002e89c121f9912d
7
+ data.tar.gz: b8c07fa4a085b8fe7b0bb1e89ad38ba3a1ebe67045f9bae77298f68468791ca37940d7829892c7029c4dd22ed97092da342932a7b50a549cba15b45704587cfd
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Russian Post API Client
2
2
 
3
- [![Build Status](https://travis-ci.org/artemshitov/russianpost.png?branch=master)](https://travis-ci.org/artemshitov/russianpost)
3
+ [![Build Status](https://travis-ci.org/artemshitov/russianpost.png?branch=master)](https://travis-ci.org/artemshitov/russianpost) [![Code Climate](https://codeclimate.com/github/artemshitov/russianpost.png)](https://codeclimate.com/github/artemshitov/russianpost)
4
4
 
5
5
  Thin wrapper around Russian Post package tracking SOAP API. Works on a per-package basis (contrary to the bulk ticket-based API). Use it at your own risk, since the API may appear unstable and require authorization in future.
6
6
 
@@ -12,7 +12,7 @@ To install gem stand-alone:
12
12
 
13
13
  To use gem in a Rails app, add the following to your `Gemfile`:
14
14
 
15
- gem "russianpost", "~> 0.3.0"
15
+ gem "russianpost", "~> 0.3.1"
16
16
 
17
17
  This gem uses [Savon](http://savonrb.com/), which in turn uses [HTTPI](https://github.com/savonrb/httpi) internally. HTTPI chooses the best HTTP library of those you have installed. For the fastest results, make sure you add [Curb](https://github.com/taf2/curb) to your `Gemfile`:
18
18
 
@@ -0,0 +1,32 @@
1
+ require "russianpost/barcode_validator"
2
+
3
+ module RussianPost
4
+ class Barcode
5
+ extend Forwardable
6
+
7
+ def_delegator :barcode, :=~
8
+
9
+ attr_reader :barcode
10
+
11
+ def initialize(barcode)
12
+ @barcode = barcode.strip.upcase
13
+ raise InvalidBarcode unless valid?
14
+ end
15
+
16
+ def to_s
17
+ barcode
18
+ end
19
+
20
+ def digits
21
+ barcode[/\d+/].split("").map { |d| d.to_i }
22
+ end
23
+
24
+ private
25
+
26
+ def valid?
27
+ BarcodeValidator.validate(self)
28
+ end
29
+ end
30
+
31
+ class InvalidBarcode < ArgumentError; end
32
+ end
@@ -0,0 +1,46 @@
1
+ module RussianPost
2
+ class BarcodeValidator
3
+ attr_reader :barcode, :digits
4
+
5
+ INTERNATIONAL_FORMAT = /\A([A-Z]{2}\d{9}[A-Z]{2})\Z/
6
+ DOMESTIC_FORMAT = /\A(\d{14})\Z/
7
+ WEIGHT_FACTORS = [8, 6, 4, 2, 3, 5, 9, 7, 0]
8
+
9
+ def self.validate(barcode)
10
+ new(barcode).valid?
11
+ end
12
+
13
+ def initialize(barcode)
14
+ @barcode = barcode
15
+ @digits = barcode.digits
16
+ end
17
+
18
+ def valid?
19
+ valid_international? || valid_domestic?
20
+ end
21
+
22
+
23
+ private
24
+
25
+ def valid_international?
26
+ barcode =~ INTERNATIONAL_FORMAT && digits.last == checkdigit
27
+ end
28
+
29
+ def valid_domestic?
30
+ barcode =~ DOMESTIC_FORMAT
31
+ end
32
+
33
+ def checkdigit
34
+ if (1..9).include? checksum
35
+ checksum
36
+ else
37
+ checksum == 10 ? 0 : 5
38
+ end
39
+ end
40
+
41
+ def checksum
42
+ product = digits.zip(WEIGHT_FACTORS)
43
+ (11 - product.map{|i| i.reduce(:*)}.reduce(:+)) % 11
44
+ end
45
+ end
46
+ end
@@ -3,11 +3,16 @@ require "savon"
3
3
  module RussianPost
4
4
  class Client
5
5
  attr_reader :savon, :endpoint, :namespace
6
+
7
+ ENDPOINT = "http://voh.russianpost.ru:8080/niips-operationhistory-web/OperationHistory"
8
+ NAMESPACE = "http://russianpost.org/operationhistory/data"
6
9
 
7
- def initialize
8
- @endpoint = "http://voh.russianpost.ru:8080/niips-operationhistory-web/OperationHistory"
9
- @namespace = "http://russianpost.org/operationhistory/data"
10
- @savon = Savon.client(endpoint: endpoint, namespace: namespace, log: false)
10
+ def initialize(opts = {})
11
+ @savon = Savon.client(
12
+ endpoint: ENDPOINT,
13
+ namespace: NAMESPACE,
14
+ open_timeout: opts[:timeout] || 10, # in seconds
15
+ log: false)
11
16
  end
12
17
 
13
18
  def call(opts = {barcode: nil})
@@ -1,15 +1,14 @@
1
1
  require "russianpost/client"
2
2
  require "russianpost/operations_factory"
3
+ require "russianpost/barcode"
3
4
 
4
5
  module RussianPost
5
6
  class Parcel
6
7
  attr_reader :barcode, :client
7
8
 
8
9
  def initialize(barcode, opts = {})
9
- @barcode = barcode.upcase
10
+ @barcode = Barcode.new(barcode)
10
11
  @client = (opts[:client] || Client).new
11
-
12
- raise InvalidBarcode unless barcode_is_valid?
13
12
  end
14
13
 
15
14
  def operations
@@ -21,11 +20,5 @@ module RussianPost
21
20
  def fetch_operations
22
21
  OperationsFactory.build(client.call(barcode: barcode))
23
22
  end
24
-
25
- def barcode_is_valid?
26
- barcode =~ /\A([A-Z]{2}\d{9}[A-Z]{2})|(\d{14})\z/
27
- end
28
23
  end
29
-
30
- class InvalidBarcode < ArgumentError; end
31
24
  end
@@ -1,3 +1,3 @@
1
1
  module Russianpost
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+ require "russianpost/barcode"
3
+
4
+ class BarcodeTest < MiniTest::Unit::TestCase
5
+ def test_implicitly_converts_to_string
6
+ barcode = RussianPost::Barcode.new("RD025500807SE")
7
+ assert_equal "bar RD025500807SE", "bar #{barcode}"
8
+ end
9
+
10
+ def test_raises_on_invalid_barcode
11
+ ["123", "RR123456789EE"].each do |barcode|
12
+ assert_raises RussianPost::InvalidBarcode do
13
+ RussianPost::Barcode.new(barcode)
14
+ end
15
+ end
16
+ end
17
+
18
+ def test_doesnt_raise_on_valid_barcode
19
+ ["RD025500807SE", "12345678901234"].each do |barcode|
20
+ RussianPost::Barcode.new(barcode)
21
+ end
22
+ end
23
+ end
@@ -12,7 +12,7 @@ class ParcelTest < MiniTest::Unit::TestCase
12
12
 
13
13
  def test_returns_empty_array_on_nonexistent_parcel
14
14
  VCR.use_cassette("nonexistent_parcel") do
15
- parcel = RussianPost::Parcel.new("RR123456789EE")
15
+ parcel = RussianPost::Parcel.new("RR123456785EE")
16
16
  assert_kind_of Array, parcel.operations
17
17
  assert parcel.operations.empty?
18
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: russianpost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Shitov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-21 00:00:00.000000000 Z
11
+ date: 2013-04-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -96,6 +96,8 @@ files:
96
96
  - README.md
97
97
  - Rakefile
98
98
  - lib/russianpost.rb
99
+ - lib/russianpost/barcode.rb
100
+ - lib/russianpost/barcode_validator.rb
99
101
  - lib/russianpost/client.rb
100
102
  - lib/russianpost/operation.rb
101
103
  - lib/russianpost/operations_factory.rb
@@ -104,6 +106,7 @@ files:
104
106
  - russianpost.gemspec
105
107
  - test/fixtures/vcr_cassettes/nonexistent_parcel.yml
106
108
  - test/fixtures/vcr_cassettes/valid_barcode.yml
109
+ - test/russianpost/barcode_test.rb
107
110
  - test/russianpost/client_test.rb
108
111
  - test/russianpost/parcel_test.rb
109
112
  - test/test_helper.rb
@@ -134,6 +137,7 @@ summary: Russian Post package tracking API client
134
137
  test_files:
135
138
  - test/fixtures/vcr_cassettes/nonexistent_parcel.yml
136
139
  - test/fixtures/vcr_cassettes/valid_barcode.yml
140
+ - test/russianpost/barcode_test.rb
137
141
  - test/russianpost/client_test.rb
138
142
  - test/russianpost/parcel_test.rb
139
143
  - test/test_helper.rb