correios-sro-xml 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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