edi_parser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +6 -0
- data/edi_parser.gemspec +26 -0
- data/lib/edi_parser/carrier_data.rb +23 -0
- data/lib/edi_parser/document_header.rb +18 -0
- data/lib/edi_parser/edi_file.rb +44 -0
- data/lib/edi_parser/interchange_header.rb +48 -0
- data/lib/edi_parser/invoice.rb +21 -0
- data/lib/edi_parser/ocurrence.rb +42 -0
- data/lib/edi_parser/version.rb +3 -0
- data/lib/edi_parser.rb +7 -0
- data/spec/edi_parser/carrier_data_spec.rb +42 -0
- data/spec/edi_parser/document_header_spec.rb +39 -0
- data/spec/edi_parser/edi_file_spec.rb +96 -0
- data/spec/edi_parser/interchange_header_spec.rb +54 -0
- data/spec/edi_parser/ocurrence_spec.rb +64 -0
- data/spec/fixtures/OCOR_ONTIME_valid.txt +3 -0
- data/spec/fixtures/OCOR_ONTIME_valid_2.txt +5 -0
- data/spec/fixtures/OCOR_invalid.txt +1 -0
- data/spec/fixtures/OCOR_invalid_carrier_data.txt +4 -0
- data/spec/fixtures/OCOR_invalid_document_header.txt +4 -0
- data/spec/fixtures/OCOR_invalid_interchange_header.txt +4 -0
- data/spec/fixtures/OCOR_valid.txt +3291 -0
- data/spec/fixtures/OCOR_valid_with_invalid_ocurrences.txt +7 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/.gitkeep +0 -0
- metadata +176 -0
data/.gitignore
ADDED
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
edi_parser
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color --format documentation
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Matheus Tardivo
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/matheustardivo/edi_parser.png?branch=master)](https://travis-ci.org/matheustardivo/edi_parser)
|
2
|
+
[![Code Climate](https://codeclimate.com/github/matheustardivo/edi_parser.png)](https://codeclimate.com/github/matheustardivo/edi_parser)
|
3
|
+
[![Coverage Status](https://coveralls.io/repos/matheustardivo/edi_parser/badge.png)](https://coveralls.io/r/matheustardivo/edi_parser)
|
4
|
+
|
5
|
+
# EdiParser
|
6
|
+
|
7
|
+
Biblioteca para fazer o parse de arquivos de ocorrências de entrega conforme o [padrão EDI COTIN/SETCESP](http://www.setcesp.org.br/cotin/index.asp).
|
8
|
+
|
9
|
+
Aqui você encontra a planilha com o layout do arquivo de ocorrências: http://www.setcesp.org.br/cotin/OCORENC.XLS
|
10
|
+
|
11
|
+
## Como usar
|
12
|
+
|
13
|
+
### Instalação
|
14
|
+
|
15
|
+
Adicione a biblioteca ao arquivo Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'edi_parser'
|
19
|
+
```
|
20
|
+
|
21
|
+
### Fazendo o parse dos seus arquivos de ocorrência
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
@edi_file = EdiParser::EdiFile.parse(path_para_seu_arquivo)
|
25
|
+
```
|
26
|
+
|
27
|
+
### Documentação
|
28
|
+
|
29
|
+
Veja no [RubyDoc.info](http://rubydoc.info) em: http://rubydoc.info/github/matheustardivo/edi_parser/master/frames
|
30
|
+
|
31
|
+
As principais classes são:
|
32
|
+
* [EdiParser::EdiFile](http://rubydoc.info/github/matheustardivo/edi_parser/master/EdiParser/EdiFile)
|
33
|
+
* [EdiParser::InterchangeHeader](http://rubydoc.info/github/matheustardivo/edi_parser/master/EdiParser/InterchangeHeader)
|
34
|
+
* [EdiParser::DocumentHeader](http://rubydoc.info/github/matheustardivo/edi_parser/master/EdiParser/DocumentHeader)
|
35
|
+
* [EdiParser::CarrierData](http://rubydoc.info/github/matheustardivo/edi_parser/master/EdiParser/CarrierData)
|
data/Rakefile
ADDED
data/edi_parser.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'edi_parser/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "edi_parser"
|
8
|
+
spec.version = EdiParser::VERSION
|
9
|
+
spec.authors = ["Matheus Tardivo"]
|
10
|
+
spec.email = ["matheustardivo@gmail.com"]
|
11
|
+
spec.summary = %q{Library simple and easy to use to parse EDI ocurrence files in the COTIN/SETCESP standards}
|
12
|
+
spec.homepage = "https://github.com/matheustardivo/edi_parser"
|
13
|
+
spec.description = spec.summary
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler" , "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake" , "~> 10.1"
|
23
|
+
spec.add_development_dependency "rspec" , "~> 2.13"
|
24
|
+
spec.add_development_dependency "pry" , "~> 0.9.12"
|
25
|
+
spec.add_development_dependency "coveralls" , "~> 0.6"
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class CarrierData
|
3
|
+
|
4
|
+
# @return [String] the carrier cnpj.
|
5
|
+
attr_accessor :cnpj
|
6
|
+
|
7
|
+
# @return [String] the carrier corporate name.
|
8
|
+
attr_accessor :corporate_name
|
9
|
+
|
10
|
+
def initialize(attributes = {})
|
11
|
+
attributes.each do |key, value|
|
12
|
+
__send__("#{key}=", value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.parse(line)
|
17
|
+
raise InvalidCarrierDataError, "Line #{line} doesn't begin with 000 header (DADOS DA TRANSPORTADORA)" unless line.start_with?("341")
|
18
|
+
CarrierData.new(cnpj: line[3..16].strip, corporate_name: line[17..56].strip)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class InvalidCarrierDataError < StandardError; end
|
23
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class DocumentHeader
|
3
|
+
|
4
|
+
# @return [String] the document header identifier.
|
5
|
+
attr_accessor :document_id
|
6
|
+
|
7
|
+
def initialize(id)
|
8
|
+
self.document_id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse(line)
|
12
|
+
raise InvalidDocumentHeaderError, "Line #{line} doesn't begin with 340 header (OCORRENCIA DA NOTA FISCAL)" unless line.start_with?("340")
|
13
|
+
DocumentHeader.new(line[3..26].strip)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class InvalidDocumentHeaderError < StandardError; end
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class EdiFile
|
3
|
+
|
4
|
+
# @return [EdiParser::InterchangeHeader] the parsed interchange header object.
|
5
|
+
attr_accessor :interchange_header
|
6
|
+
|
7
|
+
# @return [EdiParser::DocumentHeader] the parsed document header object.
|
8
|
+
attr_accessor :document_header
|
9
|
+
|
10
|
+
# @return [EdiParser::CarrierData] the parsed carrier data object.
|
11
|
+
attr_accessor :carrier_data
|
12
|
+
|
13
|
+
# @return [Array<EdiParser::Ocurrence>] the array of parse ocurrences object.
|
14
|
+
attr_accessor :ocurrences
|
15
|
+
|
16
|
+
def initialize(attributes = {})
|
17
|
+
attributes.each do |key, value|
|
18
|
+
__send__("#{key}=", value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse(file)
|
23
|
+
raise InvalidEdiFileError unless File.exists?(file)
|
24
|
+
|
25
|
+
edi_file = EdiFile.new
|
26
|
+
|
27
|
+
File.open(file) do |f|
|
28
|
+
edi_file.interchange_header = InterchangeHeader.parse(f.readline)
|
29
|
+
edi_file.document_header = DocumentHeader.parse(f.readline)
|
30
|
+
edi_file.carrier_data = CarrierData.parse(f.readline)
|
31
|
+
|
32
|
+
edi_file.ocurrences = []
|
33
|
+
f.readlines.each do |line|
|
34
|
+
ocurrence = Ocurrence.parse(line)
|
35
|
+
edi_file.ocurrences << ocurrence unless ocurrence.nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
edi_file
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class InvalidEdiFileError < StandardError; end
|
44
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class InterchangeHeader
|
3
|
+
|
4
|
+
# @return [String] the carrier name.
|
5
|
+
attr_accessor :carrier_name
|
6
|
+
|
7
|
+
# @return [String] the receiver name.
|
8
|
+
attr_accessor :receiver_name
|
9
|
+
|
10
|
+
# @return [DateTime] the processing date and time.
|
11
|
+
attr_accessor :processing_date
|
12
|
+
|
13
|
+
# @return [String] interchange header name.
|
14
|
+
attr_accessor :name
|
15
|
+
|
16
|
+
def initialize(attributes = {})
|
17
|
+
attributes.each do |key, value|
|
18
|
+
__send__("#{key}=", value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.parse(line)
|
23
|
+
raise InvalidInterchangeHeaderError, "Line #{line} doesn't begin with 000 header (CABECALHO DE INTERCAMBIO)" unless line.start_with?("000")
|
24
|
+
|
25
|
+
header = InterchangeHeader.new
|
26
|
+
|
27
|
+
header.carrier_name = line[3..37].strip
|
28
|
+
header.receiver_name = line[38..72].strip
|
29
|
+
|
30
|
+
processing_date_range = 73..82
|
31
|
+
name_range = 83..94
|
32
|
+
date_time_format = "%d%m%y%H%M"
|
33
|
+
|
34
|
+
if header.carrier_name.start_with?("ONTIME")
|
35
|
+
processing_date_range = 73..84
|
36
|
+
name_range = 85..96
|
37
|
+
date_time_format = "%d%m%Y%H%M"
|
38
|
+
end
|
39
|
+
|
40
|
+
header.processing_date = DateTime.strptime(line[processing_date_range], date_time_format)
|
41
|
+
header.name = line[name_range].strip
|
42
|
+
|
43
|
+
header
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class InvalidInterchangeHeaderError < StandardError; end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class Invoice
|
3
|
+
|
4
|
+
# @return [Integer] the invoice number.
|
5
|
+
attr_accessor :number
|
6
|
+
|
7
|
+
# @return [String] the invoice series.
|
8
|
+
attr_accessor :series
|
9
|
+
|
10
|
+
def initialize(attributes = {})
|
11
|
+
attributes.each do |key, value|
|
12
|
+
__send__("#{key}=", value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(another)
|
17
|
+
return false unless another.respond_to?(:number) && another.respond_to?(:series)
|
18
|
+
number == another.number && series == another.series
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module EdiParser
|
2
|
+
class Ocurrence
|
3
|
+
|
4
|
+
# @return [String] the sender's cnpj.
|
5
|
+
attr_accessor :sender_cnpj
|
6
|
+
|
7
|
+
# @return [EdiParser::Invoice] the invoice object.
|
8
|
+
attr_accessor :invoice
|
9
|
+
|
10
|
+
# @return [String] the ocurrence code.
|
11
|
+
attr_accessor :code
|
12
|
+
|
13
|
+
# @return [DateTime] the ocurrence date and time.
|
14
|
+
attr_accessor :date
|
15
|
+
|
16
|
+
# @return [String] the ocurrence incoming code.
|
17
|
+
attr_accessor :incoming_code
|
18
|
+
|
19
|
+
# @return [String] the ocurrence textual geoposition.
|
20
|
+
attr_accessor :geoposition
|
21
|
+
|
22
|
+
def initialize(attributes = {})
|
23
|
+
attributes.each do |key, value|
|
24
|
+
__send__("#{key}=", value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse(line)
|
29
|
+
return nil unless line.start_with?("342")
|
30
|
+
|
31
|
+
ocurrence = Ocurrence.new
|
32
|
+
ocurrence.sender_cnpj = line[3..16]
|
33
|
+
ocurrence.invoice = Invoice.new(number: line[20..27].to_i, series: line[17..19].strip)
|
34
|
+
ocurrence.code = line[28..29]
|
35
|
+
ocurrence.date = DateTime.strptime(line[30, 41], "%d%m%Y%H%M")
|
36
|
+
ocurrence.incoming_code = line[42..43].strip
|
37
|
+
ocurrence.geoposition = line[44..113].strip
|
38
|
+
|
39
|
+
ocurrence
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/edi_parser.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module EdiParser
|
4
|
+
describe CarrierData do
|
5
|
+
context "validate all attributes" do
|
6
|
+
subject {
|
7
|
+
CarrierData.new(cnpj: "Carrier cnpj", corporate_name: "Corporate name")
|
8
|
+
}
|
9
|
+
|
10
|
+
its(:cnpj) { should == "Carrier cnpj" }
|
11
|
+
its(:corporate_name) { should == "Corporate name" }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "parse invalid ocurrence EDI file" do
|
15
|
+
let(:line) { get_line(filename: "OCOR_invalid.txt") }
|
16
|
+
|
17
|
+
it "raise InvalidCarrierDataError" do
|
18
|
+
expect { CarrierData.parse(line) }.to raise_error(InvalidCarrierDataError)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "parse valid ocurrence EDI file" do
|
23
|
+
let(:line) { get_line(filename: "OCOR_valid.txt", line_number: 3) }
|
24
|
+
|
25
|
+
it "parse the carrier data" do
|
26
|
+
carrier_data = CarrierData.parse(line)
|
27
|
+
carrier_data.cnpj.should == "73939449000193"
|
28
|
+
carrier_data.corporate_name.should == "TEX COURIER LTDA"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
33
|
+
let(:line) { get_line(filename: "OCOR_ONTIME_valid.txt", line_number: 3) }
|
34
|
+
|
35
|
+
it "parse the carrier data" do
|
36
|
+
carrier_data = CarrierData.parse(line)
|
37
|
+
carrier_data.cnpj.should == "09329143000116"
|
38
|
+
carrier_data.corporate_name.should == "ONTIME LOGISTISTICA LTDA"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module EdiParser
|
4
|
+
describe DocumentHeader do
|
5
|
+
context "validate all attributes" do
|
6
|
+
subject {
|
7
|
+
DocumentHeader.new("Document id")
|
8
|
+
}
|
9
|
+
|
10
|
+
its(:document_id) { should == "Document id" }
|
11
|
+
end
|
12
|
+
|
13
|
+
context "parse invalid ocurrence EDI file" do
|
14
|
+
let(:line) { get_line(filename: "OCOR_invalid.txt") }
|
15
|
+
|
16
|
+
it "raise InvalidDocumentHeaderError" do
|
17
|
+
expect { DocumentHeader.parse(line) }.to raise_error(InvalidDocumentHeaderError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "parse valid ocurrence EDI file" do
|
22
|
+
let(:line) { get_line(filename: "OCOR_valid.txt", line_number: 2) }
|
23
|
+
|
24
|
+
it "parse the document header" do
|
25
|
+
document_header = DocumentHeader.parse(line)
|
26
|
+
document_header.document_id.should == "OCORR070611053"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
31
|
+
let(:line) { get_line(filename: "OCOR_ONTIME_valid.txt", line_number: 2) }
|
32
|
+
|
33
|
+
it "parse the document header" do
|
34
|
+
document_header = DocumentHeader.parse(line)
|
35
|
+
document_header.document_id.should == "240520131406OCOR1_ONTIME"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module EdiParser
|
4
|
+
describe EdiFile do
|
5
|
+
context "validate all attributes" do
|
6
|
+
let(:interchange_header) { mock(:interchange_header) }
|
7
|
+
let(:document_header) { mock(:document_header) }
|
8
|
+
let(:carrier_data) { mock(:carrier_data) }
|
9
|
+
let(:ocurrences) {
|
10
|
+
[mock(:ocurrence1), mock(:ocurrence2)]
|
11
|
+
}
|
12
|
+
|
13
|
+
subject {
|
14
|
+
EdiFile.new(
|
15
|
+
interchange_header: interchange_header,
|
16
|
+
document_header: document_header,
|
17
|
+
carrier_data: carrier_data,
|
18
|
+
ocurrences: ocurrences
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
its(:interchange_header) { should == interchange_header }
|
23
|
+
its(:document_header) { should == document_header }
|
24
|
+
its(:carrier_data) { should == carrier_data }
|
25
|
+
its(:ocurrences) { should == ocurrences }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
29
|
+
subject {
|
30
|
+
EdiFile.parse("spec/fixtures/OCOR_ONTIME_valid_2.txt")
|
31
|
+
}
|
32
|
+
|
33
|
+
it "have 2 ocurrences" do
|
34
|
+
subject.ocurrences.length.should == 2
|
35
|
+
end
|
36
|
+
|
37
|
+
it "first ocurrence should be valid" do
|
38
|
+
ocurrence = subject.ocurrences.first
|
39
|
+
ocurrence.sender_cnpj.should == "14314050000310"
|
40
|
+
ocurrence.invoice.should == Invoice.new(number: 122503, series: "49")
|
41
|
+
ocurrence.code.should == "01"
|
42
|
+
ocurrence.date.should == DateTime.new(2013, 6, 7, 20, 53)
|
43
|
+
ocurrence.incoming_code.should == "00"
|
44
|
+
ocurrence.geoposition.should == "ENTREGA REALIZADA"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
49
|
+
subject {
|
50
|
+
EdiFile.parse("spec/fixtures/OCOR_valid.txt")
|
51
|
+
}
|
52
|
+
|
53
|
+
it "have 3288 ocurrences" do
|
54
|
+
subject.ocurrences.length.should == 3288
|
55
|
+
end
|
56
|
+
|
57
|
+
it "first ocurrence should be valid" do
|
58
|
+
ocurrence = subject.ocurrences.first
|
59
|
+
ocurrence.sender_cnpj.should == "14314050000310"
|
60
|
+
ocurrence.invoice.should == Invoice.new(number: 185659, series: "47")
|
61
|
+
ocurrence.code.should == "95"
|
62
|
+
ocurrence.date.should == DateTime.new(2013, 6, 7, 9, 19)
|
63
|
+
ocurrence.incoming_code.should == ""
|
64
|
+
ocurrence.geoposition.should == ""
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "parse invalid EDI files" do
|
69
|
+
it "raise InvalidEdiFileError because EDI file doesn't exists" do
|
70
|
+
expect { EdiFile.parse("file_not_exists.txt") }.to raise_error(InvalidEdiFileError)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "raise InvalidInterchangeHeaderError because EDI file doesn't have a valid interchange header" do
|
74
|
+
expect { EdiFile.parse("spec/fixtures/OCOR_invalid_interchange_header.txt") }.to raise_error(InvalidInterchangeHeaderError)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "raise InvalidDocumentHeaderError because EDI file doesn't have a valid document header" do
|
78
|
+
expect { EdiFile.parse("spec/fixtures/OCOR_invalid_document_header.txt") }.to raise_error(InvalidDocumentHeaderError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "raise InvalidCarrierDataError because EDI file doesn't have a valid carrier data" do
|
82
|
+
expect { EdiFile.parse("spec/fixtures/OCOR_invalid_carrier_data.txt") }.to raise_error(InvalidCarrierDataError)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "parse valid EDI file with 2 invalid ocurrences lines" do
|
87
|
+
subject {
|
88
|
+
EdiFile.parse("spec/fixtures/OCOR_valid_with_invalid_ocurrences.txt")
|
89
|
+
}
|
90
|
+
|
91
|
+
it "have 2 ocurrences" do
|
92
|
+
subject.ocurrences.length.should == 2
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module EdiParser
|
4
|
+
describe InterchangeHeader do
|
5
|
+
context "validate all attributes" do
|
6
|
+
let(:processing_date_now) { Date.new }
|
7
|
+
subject {
|
8
|
+
InterchangeHeader.new(
|
9
|
+
carrier_name: "Carrier name",
|
10
|
+
receiver_name: "Receiver name",
|
11
|
+
processing_date: processing_date_now,
|
12
|
+
name: "Name"
|
13
|
+
)
|
14
|
+
}
|
15
|
+
|
16
|
+
its(:carrier_name) { should == "Carrier name" }
|
17
|
+
its(:receiver_name) { should == "Receiver name" }
|
18
|
+
its(:processing_date) { should == processing_date_now }
|
19
|
+
its(:name) { should == "Name" }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "parse invalid ocurrence EDI file" do
|
23
|
+
let(:line) { get_line(filename: "OCOR_invalid.txt") }
|
24
|
+
|
25
|
+
it "raise InvalidInterchangeHeaderError" do
|
26
|
+
expect { InterchangeHeader.parse(line) }.to raise_error(InvalidInterchangeHeaderError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "parse valid ocurrence EDI file" do
|
31
|
+
let(:line) { get_line(filename: "OCOR_valid.txt") }
|
32
|
+
|
33
|
+
it "parse the interchange header" do
|
34
|
+
interchange_header = InterchangeHeader.parse(line)
|
35
|
+
interchange_header.carrier_name.should == "TEX COURIER LTDA"
|
36
|
+
interchange_header.receiver_name.should == "WAL MART"
|
37
|
+
interchange_header.processing_date.should == DateTime.new(2013, 6, 7, 11, 5)
|
38
|
+
interchange_header.name.should == "OCO070611051"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
43
|
+
let(:line) { get_line(filename: "OCOR_ONTIME_valid.txt") }
|
44
|
+
|
45
|
+
it "parse the interchange header" do
|
46
|
+
interchange_header = InterchangeHeader.parse(line)
|
47
|
+
interchange_header.carrier_name.should == "ONTIME LOGISTISTICA LTDA"
|
48
|
+
interchange_header.receiver_name.should == "WMSSUPERMERCADOS DO BRASIL LTDA"
|
49
|
+
interchange_header.processing_date.should == DateTime.new(2013, 5, 24, 14, 6)
|
50
|
+
interchange_header.name.should == "OCOR1_ONTIME"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module EdiParser
|
4
|
+
describe Ocurrence do
|
5
|
+
context "validate all attributes" do
|
6
|
+
let(:date_now) { DateTime.now }
|
7
|
+
let(:invoice) { mock(:invoice, number: 9989, series: "1A") }
|
8
|
+
|
9
|
+
subject {
|
10
|
+
Ocurrence.new(
|
11
|
+
sender_cnpj: "Sender cnpj",
|
12
|
+
invoice: Invoice.new(number: 9989, series: "1A"),
|
13
|
+
code: "Code",
|
14
|
+
date: date_now,
|
15
|
+
incoming_code: "Incoming code",
|
16
|
+
geoposition: "Geoposition"
|
17
|
+
)
|
18
|
+
}
|
19
|
+
|
20
|
+
its(:sender_cnpj) { should == "Sender cnpj" }
|
21
|
+
its(:invoice) { should == invoice }
|
22
|
+
its(:code) { should == "Code" }
|
23
|
+
its(:date) { should == date_now }
|
24
|
+
its(:incoming_code) { should == "Incoming code" }
|
25
|
+
its(:geoposition) { should == "Geoposition" }
|
26
|
+
end
|
27
|
+
|
28
|
+
context "parse invalid ocurrence EDI file" do
|
29
|
+
let(:line) { get_line(filename: "OCOR_invalid.txt") }
|
30
|
+
|
31
|
+
it "return nil" do
|
32
|
+
Ocurrence.parse(line).should be_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "parse valid ocurrence EDI file" do
|
37
|
+
let(:line) { get_line(filename: "OCOR_valid.txt", line_number: 4) }
|
38
|
+
|
39
|
+
it "parse the ocurrence from EDI file in the line 4" do
|
40
|
+
ocurrence = Ocurrence.parse(line)
|
41
|
+
ocurrence.sender_cnpj.should == "14314050000310"
|
42
|
+
ocurrence.invoice.should == Invoice.new(number: 185659, series: "47")
|
43
|
+
ocurrence.code.should == "95"
|
44
|
+
ocurrence.date.should == DateTime.new(2013, 6, 7, 9, 19)
|
45
|
+
ocurrence.incoming_code.should == ""
|
46
|
+
ocurrence.geoposition.should == ""
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "parse valid ONTIME ocurrence EDI file" do
|
51
|
+
let(:line) { get_line(filename: "OCOR_ONTIME_valid_2.txt", line_number: 4) }
|
52
|
+
|
53
|
+
it "parse the carrier data" do
|
54
|
+
ocurrence = Ocurrence.parse(line)
|
55
|
+
ocurrence.sender_cnpj.should == "14314050000310"
|
56
|
+
ocurrence.invoice.should == Invoice.new(number: 122503, series: "49")
|
57
|
+
ocurrence.code.should == "01"
|
58
|
+
ocurrence.date.should == DateTime.new(2013, 6, 7, 20, 53)
|
59
|
+
ocurrence.incoming_code.should == "00"
|
60
|
+
ocurrence.geoposition.should == "ENTREGA REALIZADA"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
000ONTIME LOGISTISTICA LTDA WMSSUPERMERCADOS DO BRASIL LTDA 070620132256OCOR1_ONTIME
|
2
|
+
340070620132256OCOR1_ONTIME
|
3
|
+
34109329143000116ONTIME LOGISTISTICA LTDA
|
4
|
+
3421431405000031049 001225030107062013205300ENTREGA REALIZADA
|
5
|
+
3421431405000031049 001225030107062013205300ENTREGA REALIZADA
|
@@ -0,0 +1 @@
|
|
1
|
+
hellow
|