correios-sro-xml 0.0.4 → 0.1.0

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.
Files changed (36) hide show
  1. data/.gitignore +25 -0
  2. data/CHANGELOG.rdoc +14 -8
  3. data/Gemfile +1 -12
  4. data/README.rdoc +181 -35
  5. data/Rakefile +13 -35
  6. data/correios-sro-xml.gemspec +24 -80
  7. data/lib/correios-sro-xml.rb +4 -4
  8. data/lib/correios/sro.rb +11 -0
  9. data/lib/correios/sro/destination.rb +16 -0
  10. data/lib/correios/sro/event.rb +31 -0
  11. data/lib/correios/sro/object.rb +13 -0
  12. data/lib/correios/sro/parser.rb +5 -5
  13. data/lib/correios/sro/tracker.rb +43 -0
  14. data/lib/correios/sro/version.rb +1 -6
  15. data/lib/correios/sro/web_service.rb +64 -11
  16. data/misc/correios_sro_xml_manual_v1.5.pdf +0 -0
  17. data/spec/correios/sro/event_spec.rb +15 -0
  18. data/spec/correios/sro/parser_spec.rb +44 -44
  19. data/spec/correios/sro/tracker_spec.rb +116 -0
  20. data/spec/correios/sro/web_service_spec.rb +10 -4
  21. data/spec/correios/sro_spec.rb +22 -0
  22. data/spec/spec_helper.rb +3 -5
  23. data/spec/support/mock_request.rb +22 -0
  24. data/spec/support/responses/failure_response_not_found.xml +6 -0
  25. data/spec/support/responses/{success-response-many-objects.xml → success_response_many_objects.xml} +0 -0
  26. data/spec/support/responses/{success-response-many-objects-international.xml → success_response_many_objects_international.xml} +0 -0
  27. data/spec/support/responses/{success-response-one-object.xml → success_response_one_object.xml} +0 -0
  28. metadata +54 -59
  29. data/Gemfile.lock +0 -62
  30. data/lib/correios/sro/destino.rb +0 -16
  31. data/lib/correios/sro/evento.rb +0 -31
  32. data/lib/correios/sro/objeto.rb +0 -13
  33. data/lib/correios/sro/rastreador.rb +0 -43
  34. data/spec/correios/sro/evento_spec.rb +0 -15
  35. data/spec/correios/sro/rastreador_spec.rb +0 -53
  36. data/spec/support/fake_request.rb +0 -21
@@ -1,10 +1,10 @@
1
1
  # encoding: UTF-8
2
2
  require 'rubygems'
3
3
  require 'correios/sro'
4
- require 'correios/sro/destino'
5
- require 'correios/sro/evento'
6
- require 'correios/sro/objeto'
4
+ require 'correios/sro/destination'
5
+ require 'correios/sro/event'
6
+ require 'correios/sro/object'
7
7
  require 'correios/sro/parser'
8
- require 'correios/sro/rastreador'
8
+ require 'correios/sro/tracker'
9
9
  require 'correios/sro/string'
10
10
  require 'correios/sro/web_service'
data/lib/correios/sro.rb CHANGED
@@ -4,5 +4,16 @@ require 'log-me'
4
4
  module Correios
5
5
  module SRO
6
6
  extend LogMe
7
+
8
+ module Timeout
9
+ DEFAULT_REQUEST_TIMEOUT = 5 #seconds
10
+ attr_writer :request_timeout
11
+
12
+ def request_timeout
13
+ (@request_timeout ||= DEFAULT_REQUEST_TIMEOUT).to_i
14
+ end
15
+ end
16
+
17
+ extend Timeout
7
18
  end
8
19
  end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ require 'sax-machine'
3
+
4
+ module Correios
5
+ module SRO
6
+ class Destination
7
+ include SAXMachine
8
+
9
+ element :local, :as => :place
10
+ element :codigo, :as => :code
11
+ element :cidade, :as => :city
12
+ element :bairro, :as => :neighborhood
13
+ element :uf, :as => :state
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: UTF-8
2
+ require 'sax-machine'
3
+
4
+ module Correios
5
+ module SRO
6
+ class Event
7
+ include SAXMachine
8
+
9
+ element :tipo, :as => :type
10
+ element :status, :as => :status
11
+ element :data, :as => :date
12
+ element :hora, :as => :hour
13
+ element :descricao, :as => :description
14
+ element :recebedor, :as => :receiver
15
+ element :documento, :as => :document
16
+ element :comentario, :as => :comment
17
+ element :local, :as => :place
18
+ element :codigo, :as => :code
19
+ element :cidade, :as => :city
20
+ element :uf, :as => :state
21
+ element :sto, :as => :sto
22
+ element :destino, :as => :destination, :class => Correios::SRO::Destination
23
+
24
+ [:receiver, :document, :comment].each do |method|
25
+ define_method "#{method}=" do |value|
26
+ instance_variable_set("@#{method}", value.to_s.strip)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+ require 'sax-machine'
3
+
4
+ module Correios
5
+ module SRO
6
+ class Object
7
+ include SAXMachine
8
+
9
+ element :numero, :as => :number
10
+ elements :evento, :as => :events, :class => Correios::SRO::Event
11
+ end
12
+ end
13
+ end
@@ -4,17 +4,17 @@ require 'nokogiri'
4
4
  module Correios
5
5
  module SRO
6
6
  class Parser
7
- def objetos(xml)
8
- objetos = {}
7
+ def objects(xml)
8
+ objects = {}
9
9
  xml = xml.backward_encode("UTF-8", "ISO-8859-1")
10
10
 
11
11
  doc = Nokogiri::XML(xml)
12
12
  doc.xpath("//objeto").each do |element|
13
- objeto = Correios::SRO::Objeto.parse(element.to_xml)
14
- objetos[objeto.numero] = objeto
13
+ object = Correios::SRO::Object.parse(element.to_xml)
14
+ objects[object.number] = object
15
15
  end
16
16
 
17
- objetos
17
+ objects
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+ module Correios
3
+ module SRO
4
+ class Tracker
5
+ attr_accessor :user, :password
6
+ attr_accessor :query_type, :result_mode
7
+ attr_reader :object_numbers
8
+
9
+ DEFAULT_OPTIONS = { :query_type => :list, :result_mode => :last }
10
+
11
+ def initialize(options = {})
12
+ DEFAULT_OPTIONS.merge(options).each do |attr, value|
13
+ self.send("#{attr}=", value)
14
+ end
15
+
16
+ yield self if block_given?
17
+ @object_numbers = []
18
+ end
19
+
20
+ def get(*object_numbers)
21
+ @object_numbers = object_numbers
22
+ response = web_service.request!
23
+ objects = parser.objects(response)
24
+
25
+ if @object_numbers.size == 1
26
+ objects.values.first
27
+ else
28
+ objects
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def web_service
35
+ @web_service ||= Correios::SRO::WebService.new(self)
36
+ end
37
+
38
+ def parser
39
+ @parser ||= Correios::SRO::Parser.new
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,12 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  module Correios
3
3
  module SRO
4
- module Version
5
- MAJOR = 0
6
- MINOR = 0
7
- PATCH = 4
8
- VERSION = [MAJOR, MINOR, PATCH].join(".")
9
- end
4
+ VERSION = "0.1.0"
10
5
  end
11
6
  end
12
7
 
@@ -6,29 +6,82 @@ module Correios
6
6
  module SRO
7
7
  class WebService
8
8
  URL = "http://websro.correios.com.br/sro_bin/sroii_xml.eventos"
9
- TYPES = { :lista => "L", :intervalo => "F" }
10
- RESULTS = { :todos => "T", :ultimo => "U" }
9
+ QUERY_TYPES = { :list => "L", :range => "F" }
10
+ RESULT_MODES = { :all => "T", :last => "U" }
11
11
 
12
- def initialize
12
+ def initialize(tracker)
13
13
  @uri = URI.parse(URL)
14
+ @tracker = tracker
14
15
  end
15
16
 
16
- def request(sro)
17
- response = Net::HTTP.post_form(@uri, params_for(sro))
17
+ def request!
18
+ http = build_http
19
+
20
+ request = build_request
21
+ log_request(request)
22
+
23
+ response = http.request(request)
24
+ log_response(response)
25
+
18
26
  response.body
19
27
  end
20
28
 
21
29
  private
22
30
 
23
- def params_for(sro)
31
+ def build_http
32
+ http = Net::HTTP.new(@uri.host, @uri.port)
33
+ http.open_timeout = Correios::SRO.request_timeout
34
+ http
35
+ end
36
+
37
+ def build_request
38
+ request = Net::HTTP::Post.new(@uri.path)
39
+ request.set_form_data(request_params)
40
+ request
41
+ end
42
+
43
+ def request_params
24
44
  {
25
- :Usuario => sro.usuario,
26
- :Senha => sro.senha,
27
- :Tipo => TYPES[sro.tipo],
28
- :Resultado => RESULTS[sro.resultado],
29
- :Objetos => sro.objetos.join
45
+ :Usuario => @tracker.user,
46
+ :Senha => @tracker.password,
47
+ :Tipo => QUERY_TYPES[@tracker.query_type],
48
+ :Resultado => RESULT_MODES[@tracker.result_mode],
49
+ :Objetos => @tracker.object_numbers.join
30
50
  }
31
51
  end
52
+
53
+ def log_request(request)
54
+ message = format_message(request) do
55
+ message = with_line_break { "Correios-SRO-XML Request:" }
56
+ message << with_line_break { "POST #{URL}" }
57
+ end
58
+
59
+ Correios::SRO.log(message)
60
+ end
61
+
62
+ def log_response(response)
63
+ message = format_message(response) do
64
+ message = with_line_break { "Correios-SRO-XML Response:" }
65
+ message << with_line_break { "HTTP/#{response.http_version} #{response.code} #{response.message}" }
66
+ end
67
+
68
+ Correios::SRO.log(message)
69
+ end
70
+
71
+ def format_message(http)
72
+ message = yield
73
+ message << with_line_break { format_headers_for(http) } if Correios::SRO.log_level == :debug
74
+ message << with_line_break { http.body }
75
+ end
76
+
77
+ def format_headers_for(http)
78
+ # I'm using an empty block in each_header method for Ruby 1.8.7 compatibility.
79
+ http.each_header{}.map { |name, values| "#{name}: #{values.first}" }.join("\n")
80
+ end
81
+
82
+ def with_line_break
83
+ "#{yield}\n"
84
+ end
32
85
  end
33
86
  end
34
87
  end
@@ -0,0 +1,15 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Correios::SRO::Event do
5
+ let(:event) { Correios::SRO::Event.new }
6
+
7
+ [:receiver, :document, :comment].each do |method|
8
+ describe "##{method}=" do
9
+ it "strips string" do
10
+ event.send("#{method}=", " Texto. ")
11
+ event.send(method).should == "Texto."
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,87 +2,87 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Correios::SRO::Parser do
5
- describe "#objetos" do
5
+ describe "#objects" do
6
6
  let(:xml) { body_for :success_response_many_objects }
7
7
  let(:parser) { Correios::SRO::Parser.new }
8
8
 
9
9
  it "encodes from ISO-8859-1 to UTF-8" do
10
10
  xml.should_receive(:backward_encode).with("UTF-8", "ISO-8859-1").and_return(xml)
11
- parser.objetos(xml)
11
+ parser.objects(xml)
12
12
  end
13
13
 
14
14
  ["SI047624825BR", "SX104110463BR"].each do |number|
15
15
  it "returns object number" do
16
- objetos = parser.objetos(xml)
17
- objetos[number].numero.should == number
16
+ objects = parser.objects(xml)
17
+ objects[number].number.should == number
18
18
  end
19
19
  end
20
20
 
21
21
  context "returns event" do
22
- before(:each) { @objetos = parser.objetos(xml) }
22
+ before(:each) { @objects = parser.objects(xml) }
23
23
 
24
24
  { "SI047624825BR" => {
25
- :tipo => "BDI",
25
+ :type => "BDI",
26
26
  :status => "01",
27
- :data => "26/12/2011",
28
- :hora => "15:22",
29
- :descricao => "Entregue",
30
- :recebedor => "",
31
- :documento => "",
32
- :comentario => "?",
33
- :local => "AC CENTRAL DE SAO PAULO",
34
- :codigo => "01009972",
35
- :cidade => "SAO PAULO",
36
- :uf => "SP",
27
+ :date => "26/12/2011",
28
+ :hour => "15:22",
29
+ :description => "Entregue",
30
+ :receiver => "",
31
+ :document => "",
32
+ :comment => "?",
33
+ :place => "AC CENTRAL DE SAO PAULO",
34
+ :code => "01009972",
35
+ :city => "SAO PAULO",
36
+ :state => "SP",
37
37
  :sto => "00024419"
38
38
  },
39
39
  "SX104110463BR" => {
40
- :tipo => "BDE",
40
+ :type => "BDE",
41
41
  :status => "01",
42
- :data => "08/12/2011",
43
- :hora => "09:30",
44
- :descricao => "Entregue",
45
- :recebedor => "",
46
- :documento => "",
47
- :comentario => "",
48
- :local => "CEE JUNDIAI",
49
- :codigo => "13211970",
50
- :cidade => "JUNDIAI",
51
- :uf => "SP",
42
+ :date => "08/12/2011",
43
+ :hour => "09:30",
44
+ :description => "Entregue",
45
+ :receiver => "",
46
+ :document => "",
47
+ :comment => "",
48
+ :place => "CEE JUNDIAI",
49
+ :code => "13211970",
50
+ :city => "JUNDIAI",
51
+ :state => "SP",
52
52
  :sto => "74654209"
53
53
  },
54
54
  }.each do |number, first_event|
55
55
  first_event.each do |attr, value|
56
56
  it attr do
57
- evento = @objetos[number].eventos.first
58
- evento.send(attr).should == value
57
+ event = @objects[number].events.first
58
+ event.send(attr).should == value
59
59
  end
60
60
  end
61
61
  end
62
62
  end
63
63
 
64
64
  context "returns destination" do
65
- before(:each) { @objetos = parser.objetos(xml) }
65
+ before(:each) { @objects = parser.objects(xml) }
66
66
 
67
67
  { "SI047624825BR" => {
68
- :local => "CTE VILA MARIA",
69
- :codigo => "02170975",
70
- :cidade => "SAO PAULO",
71
- :bairro => "PQ NOVO MUNDO",
72
- :uf => "SP"
68
+ :place => "CTE VILA MARIA",
69
+ :code => "02170975",
70
+ :city => "SAO PAULO",
71
+ :neighborhood => "PQ NOVO MUNDO",
72
+ :state => "SP"
73
73
  },
74
74
  "SX104110463BR" => {
75
- :local => "CTE CAMPINAS",
76
- :codigo => "13050971",
77
- :cidade => "VALINHOS",
78
- :bairro => "MACUCO",
79
- :uf => "SP"
75
+ :place => "CTE CAMPINAS",
76
+ :code => "13050971",
77
+ :city => "VALINHOS",
78
+ :neighborhood => "MACUCO",
79
+ :state => "SP"
80
80
  },
81
- }.each do |number, destination|
82
- destination.each do |attr, value|
81
+ }.each do |number, destinations|
82
+ destinations.each do |attr, value|
83
83
  it attr do
84
- destino = @objetos[number].eventos[3].destino
85
- destino.send(attr).should == value
84
+ destination = @objects[number].events[3].destination
85
+ destination.send(attr).should == value
86
86
  end
87
87
  end
88
88
  end
@@ -0,0 +1,116 @@
1
+ # encoding: UTF-8
2
+ require 'spec_helper'
3
+
4
+ describe Correios::SRO::Tracker do
5
+ describe ".new" do
6
+ it "creates with default values" do
7
+ sro = Correios::SRO::Tracker.new
8
+ sro.query_type.should == :list
9
+ sro.result_mode.should == :last
10
+ sro.object_numbers.should == []
11
+ end
12
+
13
+ { :user => "PRODIS",
14
+ :password => "pim321",
15
+ :query_type => :range,
16
+ :result_mode => :all
17
+ }.each do |attr, value|
18
+ context "when #{attr} is supplied" do
19
+ it "sets #{attr}" do
20
+ sro = Correios::SRO::Tracker.new(attr => value)
21
+ sro.send(attr).should == value
22
+ end
23
+ end
24
+
25
+ context "when #{attr} is supplied in a block" do
26
+ it "sets #{attr}" do
27
+ sro = Correios::SRO::Tracker.new { |t| t.send("#{attr}=", value) }
28
+ sro.send(attr).should == value
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#get" do
35
+ around do |example|
36
+ Correios::SRO.configure { |config| config.log_enabled = false }
37
+ example.run
38
+ Correios::SRO.configure { |config| config.log_enabled = true }
39
+ end
40
+
41
+ let(:sro) { Correios::SRO::Tracker.new(:user => "PRODIS", :password => "pim321") }
42
+
43
+ context "to many objects" do
44
+ before(:each) { mock_request_for(:success_response_many_objects) }
45
+
46
+ it "sets objects numbers" do
47
+ sro.get("SI047624825BR", "SX104110463BR")
48
+ sro.object_numbers.size.should == 2
49
+ sro.object_numbers.first.should == "SI047624825BR"
50
+ sro.object_numbers.last.should == "SX104110463BR"
51
+ end
52
+
53
+ it "creates a WebService with correct params" do
54
+ web_service = Correios::SRO::WebService.new(sro)
55
+ Correios::SRO::WebService.should_receive(:new).with(sro).and_return(web_service)
56
+ sro.get("SI047624825BR", "SX104110463BR")
57
+ end
58
+
59
+ it "returns all objects" do
60
+ objects = sro.get("SI047624825BR", "SX104110463BR")
61
+ objects.size.should == 2
62
+ objects["SI047624825BR"].number.should == "SI047624825BR"
63
+ objects["SX104110463BR"].number.should == "SX104110463BR"
64
+ end
65
+
66
+ context "when only one object found" do
67
+ before(:each) { mock_request_for(:success_response_one_object) }
68
+
69
+ it "returns a Hash" do
70
+ objects = sro.get("SI047624825BR", "SX104110463BR")
71
+ objects.should be_an_instance_of Hash
72
+ end
73
+
74
+ it "returns the object found" do
75
+ objects = sro.get("SI047624825BR", "SX104110463BR")
76
+ objects.size.should == 1
77
+ objects["SI047624825BR"].number.should == "SI047624825BR"
78
+ end
79
+
80
+ it "returns nil in object not found" do
81
+ objects = sro.get("SI047624825BR", "SX104110463BR")
82
+ objects["SX104110463BR"].should be_nil
83
+ end
84
+ end
85
+ end
86
+
87
+ context "to one object" do
88
+ before(:each) { mock_request_for(:success_response_one_object) }
89
+
90
+ it "sets object number" do
91
+ sro.get("SI047624825BR")
92
+ sro.object_numbers.size.should == 1
93
+ sro.object_numbers.first.should == "SI047624825BR"
94
+ end
95
+
96
+ it "creates a WebService with correct params" do
97
+ web_service = Correios::SRO::WebService.new(sro)
98
+ Correios::SRO::WebService.should_receive(:new).with(sro).and_return(web_service)
99
+ sro.get("SI047624825BR")
100
+ end
101
+
102
+ it "returns only one object" do
103
+ object = sro.get("SI047624825BR")
104
+ object.number.should == "SI047624825BR"
105
+ end
106
+
107
+ context "when object not found" do
108
+ it "returns nil" do
109
+ mock_request_for(:failure_response_not_found)
110
+ object = sro.get("SI047624825BR")
111
+ object.should be_nil
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end