gentle 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +9 -0
- data/gentle.gemspec +29 -0
- data/lib/gentle.rb +8 -0
- data/lib/gentle/blackboard.rb +44 -0
- data/lib/gentle/client.rb +92 -0
- data/lib/gentle/documents/document.rb +15 -0
- data/lib/gentle/documents/request/hash_converter.rb +55 -0
- data/lib/gentle/documents/request/shipment_order.rb +167 -0
- data/lib/gentle/documents/response/shipment_order_result.rb +56 -0
- data/lib/gentle/error_message.rb +19 -0
- data/lib/gentle/message.rb +43 -0
- data/lib/gentle/phase_1_set.rb +53 -0
- data/lib/gentle/queue.rb +40 -0
- data/lib/gentle/request.rb +11 -0
- data/lib/gentle/response.rb +11 -0
- data/lib/gentle/version.rb +3 -0
- data/spec/fixtures/credentials.yml +12 -0
- data/spec/fixtures/documents/responses/shipment_order_result.xml +23 -0
- data/spec/fixtures/messages/error_message.xml +10 -0
- data/spec/fixtures/messages/purchase_order_message.xml +11 -0
- data/spec/remote/blackboard_spec.rb +43 -0
- data/spec/remote/queue_spec.rb +64 -0
- data/spec/spec_helper.rb +323 -0
- data/spec/unit/blackboard_spec.rb +102 -0
- data/spec/unit/client_spec.rb +97 -0
- data/spec/unit/documents/document_spec.rb +44 -0
- data/spec/unit/documents/request/hash_converter_spec.rb +42 -0
- data/spec/unit/documents/request/shipment_order_spec.rb +164 -0
- data/spec/unit/documents/response/shipment_order_result_spec.rb +26 -0
- data/spec/unit/error_message_spec.rb +31 -0
- data/spec/unit/message_spec.rb +71 -0
- data/spec/unit/phase_1_set_spec.rb +76 -0
- data/spec/unit/queue_spec.rb +57 -0
- metadata +196 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'time'
|
2
|
+
module Gentle
|
3
|
+
module Documents
|
4
|
+
module Response
|
5
|
+
class ShipmentOrderResult
|
6
|
+
attr_reader :io
|
7
|
+
|
8
|
+
def initialize(options = {})
|
9
|
+
@io = options[:io]
|
10
|
+
@document = Nokogiri::XML::Document.parse(@io)
|
11
|
+
end
|
12
|
+
|
13
|
+
def client_id
|
14
|
+
@client_id ||= so_result['ClientID']
|
15
|
+
end
|
16
|
+
|
17
|
+
def business_unit
|
18
|
+
@business_unit ||= so_result['BusinessUnit']
|
19
|
+
end
|
20
|
+
|
21
|
+
def date_shipped
|
22
|
+
@date_shipped ||= Time.parse(so_result['DateShipped']).utc
|
23
|
+
end
|
24
|
+
|
25
|
+
def order_number
|
26
|
+
@order_number ||= so_result['OrderNumber']
|
27
|
+
end
|
28
|
+
|
29
|
+
def carton_count
|
30
|
+
@carton_count ||= so_result['CartonCount'].to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
def carrier
|
34
|
+
@carrier ||= carton['Carrier']
|
35
|
+
end
|
36
|
+
|
37
|
+
def service_level
|
38
|
+
@service_level ||= carton['ServiceLevel']
|
39
|
+
end
|
40
|
+
|
41
|
+
def tracking_number
|
42
|
+
@tracking_number ||= carton['TrackingId']
|
43
|
+
end
|
44
|
+
|
45
|
+
def so_result
|
46
|
+
@so_result ||= @document.css('SOResult').first
|
47
|
+
end
|
48
|
+
|
49
|
+
def carton
|
50
|
+
@carton ||= @document.css('Carton').first
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Gentle
|
2
|
+
class ErrorMessage
|
3
|
+
attr_reader :xml
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@xml = Nokogiri::XML::Document.parse(options[:xml]) if options[:xml]
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_xml
|
10
|
+
@xml.serialize(encoding: "UTF-8")
|
11
|
+
end
|
12
|
+
|
13
|
+
def shipment_number
|
14
|
+
result_description = @xml.css("ErrorMessage").first["ResultDescription"]
|
15
|
+
match_data = result_description.match(/(.+)_(.+)_(.+)_.*.xml/) unless result_description.nil?
|
16
|
+
match_data[2] unless match_data.nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Gentle
|
2
|
+
class Message
|
3
|
+
|
4
|
+
NAMESPACE = "http://schemas.quietlogistics.com/V2/EventMessage.xsd"
|
5
|
+
|
6
|
+
class MissingDocumentError < StandardError; end
|
7
|
+
class MissingClientError < StandardError; end
|
8
|
+
|
9
|
+
attr_reader :client, :document, :xml
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@xml = Nokogiri::XML::Document.parse(options[:xml]) if options[:xml]
|
13
|
+
@client = options[:client]
|
14
|
+
@document = options[:document]
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_xml
|
18
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
19
|
+
xml.EventMessage(attributes)
|
20
|
+
end
|
21
|
+
builder.to_xml
|
22
|
+
end
|
23
|
+
|
24
|
+
def document_type
|
25
|
+
@document ? @document.type : @xml.css('EventMessage').first['DocumentType']
|
26
|
+
end
|
27
|
+
|
28
|
+
def document_name
|
29
|
+
@document ? @document.filename : @xml.css('EventMessage').first['DocumentName']
|
30
|
+
end
|
31
|
+
|
32
|
+
def attributes
|
33
|
+
raise(MissingClientError.new("client cannot be missing")) unless @client
|
34
|
+
raise(MissingDocumentError.new("document cannot be missing")) unless @document
|
35
|
+
{
|
36
|
+
ClientId: @client.client_id, BusinessUnit: @client.business_unit,
|
37
|
+
DocumentName: @document.filename, DocumentType: @document.type,
|
38
|
+
Warehouse: @document.warehouse, MessageDate: @document.date.utc.iso8601,
|
39
|
+
MessageId: @document.message_id, xmlns: NAMESPACE
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Gentle
|
2
|
+
class Phase1Set
|
3
|
+
|
4
|
+
SKUS = {
|
5
|
+
"GPS1-5" => "GPST100 - 2",
|
6
|
+
"GPS2-5" => "GPST200 - 2",
|
7
|
+
"GPS3-5" => "GPST300",
|
8
|
+
"GPS4-5" => "GPST400",
|
9
|
+
"GPS5-5" => "GPST500"
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(item)
|
13
|
+
@item = item
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.match(item)
|
17
|
+
SKUS.key? item.sku
|
18
|
+
end
|
19
|
+
|
20
|
+
def included_items
|
21
|
+
[
|
22
|
+
milky_jelly,
|
23
|
+
priming_moisturizer,
|
24
|
+
balm_dotcom,
|
25
|
+
skin_tint
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
def milky_jelly
|
30
|
+
line_item(97 , "GMJC100", 18.0)
|
31
|
+
end
|
32
|
+
|
33
|
+
def priming_moisturizer
|
34
|
+
line_item( 3, "GPM100", 25.0)
|
35
|
+
end
|
36
|
+
|
37
|
+
def balm_dotcom
|
38
|
+
line_item(96, "GBD100-3", 12.0)
|
39
|
+
end
|
40
|
+
|
41
|
+
def skin_tint
|
42
|
+
line_item(6, SKUS[@item.sku], 26.0)
|
43
|
+
end
|
44
|
+
|
45
|
+
def line_item(id, sku, price)
|
46
|
+
LineItem.new(sku, id, @item.quantity, price)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class LineItem < Struct.new(:sku, :id, :quantity, :price)
|
52
|
+
end
|
53
|
+
end
|
data/lib/gentle/queue.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Gentle
|
2
|
+
class Queue
|
3
|
+
attr_reader :client
|
4
|
+
def initialize(client)
|
5
|
+
@client = client
|
6
|
+
end
|
7
|
+
|
8
|
+
def send(message)
|
9
|
+
queue = client.to_quiet_queue
|
10
|
+
queue.send_message(message.to_xml)
|
11
|
+
end
|
12
|
+
|
13
|
+
def receive
|
14
|
+
queue = client.from_quiet_queue
|
15
|
+
message = nil
|
16
|
+
queue.receive_message do |msg|
|
17
|
+
message = build_message(msg)
|
18
|
+
end
|
19
|
+
message || Message.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def approximate_pending_messages
|
23
|
+
client.from_quiet_queue.approximate_number_of_messages
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def build_message(msg)
|
29
|
+
if received_error? msg
|
30
|
+
ErrorMessage.new(xml: msg.body)
|
31
|
+
else
|
32
|
+
Message.new(xml: msg.body)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def received_error?(msg)
|
37
|
+
msg.body.include? "<ErrorMessage"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
access_key_id: abracadabra
|
2
|
+
secret_access_key: alakazam
|
3
|
+
client_id: Gentle
|
4
|
+
business_unit: Gentle
|
5
|
+
warehouse: SPACE
|
6
|
+
buckets:
|
7
|
+
to: gentle-to-quiet
|
8
|
+
from: gentle-from-quiet
|
9
|
+
queues:
|
10
|
+
to: http://queue.amazonaws/1234567890/gentle_to_quiet
|
11
|
+
from: http://queue.amazonaws/1234567890/gentle_from_quiet
|
12
|
+
inventory: http://queue.amazonaws/1234567890/gentle_inventory
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<SOResult
|
3
|
+
xmlns="http://schemas.quiettechnology.com/V2/SOResultDocument.xsd"
|
4
|
+
ClientID="Gentle"
|
5
|
+
BusinessUnit="Gentle"
|
6
|
+
CartonCount="1"
|
7
|
+
DateShipped="2009-09-01T04:00:00Z"
|
8
|
+
FreightCost="10.00"
|
9
|
+
OrderNumber="1234567890">
|
10
|
+
<Line Line="1" Quantity="1" />
|
11
|
+
<Line Line="2" Quantity="1" />
|
12
|
+
<Carton
|
13
|
+
Carrier="USPS"
|
14
|
+
CartonId="S12345678901"
|
15
|
+
CartonNumber="1"
|
16
|
+
FreightCost="10.00"
|
17
|
+
ServiceLevel="FIRST"
|
18
|
+
TrackingId="40000000000"
|
19
|
+
Weight="0.66">
|
20
|
+
<Content Line="1"Quantity="1" />
|
21
|
+
<Content Line="2"Quantity="1" />
|
22
|
+
</Carton>
|
23
|
+
</SOResult>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<ErrorMessage
|
3
|
+
xmlns="http://schemas.quietlogistics.com/V2/EventMessageErrorResponse.xsd"
|
4
|
+
OriginalMessageId="ab6e7e7a-6d45-4c75-9fec-e08dba4a9c31"
|
5
|
+
ResponseDate="2009-09-01T12:00:00Z"
|
6
|
+
ClientId="Gentle"
|
7
|
+
BusinessUnit="Gentle"
|
8
|
+
ResultCode="1030"
|
9
|
+
ResultDescription="Document: Gentle_ShipmentOrder_H123456789_20160229_135723.xml - Error: An error has occured">
|
10
|
+
</ErrorMessage>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<EventMessage
|
3
|
+
xmlns="http://schemas.quietlogistics.com/V2/EventMessage.xsd"
|
4
|
+
ClientId="Gentle"
|
5
|
+
BusinessUnit="Gentle"
|
6
|
+
DocumentName="Gentle_PurchaseOrder_1234_20100927_132505124.xml"
|
7
|
+
DocumentType="PurchaseOrder"
|
8
|
+
MessageId="EF1CE966-38A2-428b-BA67-EFF23AF22F57"
|
9
|
+
Warehouse="CORP1"
|
10
|
+
MessageDate="2009-09-01T12:00:00Z">
|
11
|
+
</EventMessage>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'gentle'
|
3
|
+
require 'gentle/blackboard'
|
4
|
+
|
5
|
+
module Gentle
|
6
|
+
describe "BlackboardRemote" do
|
7
|
+
include Configuration
|
8
|
+
include Fixtures
|
9
|
+
|
10
|
+
before do
|
11
|
+
AWS.config(stub_requests: false)
|
12
|
+
@client = Client.new(load_configuration)
|
13
|
+
@blackboard = Blackboard.new(@client)
|
14
|
+
@document = DocumentDouble.new(
|
15
|
+
message_id: '1234567',
|
16
|
+
date: Time.new(2013, 04, 05, 12, 30, 15).utc,
|
17
|
+
filename: 'neat_beans.xml',
|
18
|
+
client: @client,
|
19
|
+
type: 'ShipmentOrderResult'
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
buckets = [@client.to_quiet_bucket, @client.from_quiet_bucket]
|
25
|
+
buckets.each { |bucket| bucket.objects.delete_all }
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should be able to write a document to an S3 bucket" do
|
29
|
+
message = @blackboard.post(@document)
|
30
|
+
file = message.document_name
|
31
|
+
bucket = @client.to_quiet_bucket
|
32
|
+
assert bucket.objects[file].exists?, "It appears that #{file} was not written to S3"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be able to fetch a document from an S3 bucket when given a message" do
|
36
|
+
expected_contents = load_response('shipment_order_result')
|
37
|
+
@client.from_quiet_bucket.objects[@document.filename].write(expected_contents)
|
38
|
+
message = MessageDouble.new(document_name: @document.filename, document_type: @document.type)
|
39
|
+
document = @blackboard.fetch(message)
|
40
|
+
assert_equal expected_contents, document.io
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'openssl'
|
3
|
+
require 'gentle'
|
4
|
+
require 'gentle/message'
|
5
|
+
|
6
|
+
module Gentle
|
7
|
+
describe "QueueRemote" do
|
8
|
+
include Configuration
|
9
|
+
|
10
|
+
before do
|
11
|
+
AWS.config(:stub_requests => false)
|
12
|
+
@client = Client.new(load_configuration)
|
13
|
+
@sqs_queues = [@client.to_quiet_queue, @client.from_quiet_queue]
|
14
|
+
@default_wait_time = @sqs_queues.map(&:wait_time_seconds).max
|
15
|
+
@sqs_queues.each { |queue| queue.wait_time_seconds = 1 }
|
16
|
+
|
17
|
+
@document = DocumentDouble.new(
|
18
|
+
:message_id => '1234567',
|
19
|
+
:date => Time.new(2013, 04, 05, 12, 30, 15).utc,
|
20
|
+
:filename => 'neat_beans.xml',
|
21
|
+
:client => @client,
|
22
|
+
:type => 'Thinger'
|
23
|
+
)
|
24
|
+
|
25
|
+
@message = Message.new(:client => @client, :document => @document)
|
26
|
+
@queue = Queue.new(@client)
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
@sqs_queues.each do |queue|
|
31
|
+
flush(queue)
|
32
|
+
end
|
33
|
+
@sqs_queues.each { |queue| queue.wait_time_seconds = @default_wait_time }
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be able to push a message onto the queue" do
|
37
|
+
expected_md5 = OpenSSL::Digest::MD5.new.hexdigest(@message.to_xml)
|
38
|
+
sent_message = @queue.send(@message)
|
39
|
+
# NOTE: This is failing, but the message is getting sent
|
40
|
+
# assert_equal 1, @client.to_quiet_queue.approximate_number_of_messages
|
41
|
+
assert_equal expected_md5, sent_message.md5
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should be able to fetch a message from the queue" do
|
45
|
+
@client.from_quiet_queue.send_message(@message.to_xml)
|
46
|
+
message = @queue.receive
|
47
|
+
|
48
|
+
assert_equal @message.document_type, message.document_type
|
49
|
+
assert_equal @message.document_name, message.document_name
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def flush(queue)
|
54
|
+
pending_messages = queue.approximate_number_of_messages
|
55
|
+
while pending_messages > 0
|
56
|
+
queue.receive_message do |message|
|
57
|
+
message.delete
|
58
|
+
pending_messages -= 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,323 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'yaml'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require 'gentle'
|
6
|
+
require 'pry'
|
7
|
+
|
8
|
+
module Fixtures
|
9
|
+
def load_fixture(path)
|
10
|
+
File.open(path, 'rb').read
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_response(response_name)
|
14
|
+
load_fixture("spec/fixtures/documents/responses/#{response_name}.xml")
|
15
|
+
end
|
16
|
+
|
17
|
+
def load_message(message_name)
|
18
|
+
load_fixture("spec/fixtures/messages/#{message_name}.xml")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Configuration
|
23
|
+
def load_configuration
|
24
|
+
test_credentials_file = ENV['HOME'] + '/.gentle/credentials.yml'
|
25
|
+
test_credentials_file = "spec/fixtures/credentials.yml" unless File.exists?(test_credentials_file)
|
26
|
+
YAML.load(File.open(test_credentials_file, 'rb'))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class VariantDouble
|
31
|
+
DEFAULT_OPTIONS = {
|
32
|
+
id: 112233,
|
33
|
+
sku: "ABC-123",
|
34
|
+
price: '6.95'
|
35
|
+
}
|
36
|
+
|
37
|
+
attr_reader :id, :sku, :price
|
38
|
+
def initialize(options = {})
|
39
|
+
@id = options[:id]
|
40
|
+
@sku = options[:sku]
|
41
|
+
@price = options[:price]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.example(options = {})
|
45
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class LineItemDouble
|
50
|
+
DEFAULT_OPTIONS = {
|
51
|
+
id: 123456,
|
52
|
+
quantity: 1,
|
53
|
+
price: '12.95',
|
54
|
+
sku: "ABC-123",
|
55
|
+
part_line_items: []
|
56
|
+
}
|
57
|
+
|
58
|
+
attr_reader :id, :quantity, :price, :sku, :product, :part_line_items
|
59
|
+
def initialize(options = {})
|
60
|
+
@id = options[:id]
|
61
|
+
@quantity = options[:quantity]
|
62
|
+
@price = options[:price]
|
63
|
+
@sku = options[:sku]
|
64
|
+
@product = options[:product]
|
65
|
+
|
66
|
+
@part_line_items = options[:part_line_items].map do |part|
|
67
|
+
PartLineItemDouble.example(
|
68
|
+
id: part.id,
|
69
|
+
variant: part.variant,
|
70
|
+
line_item: LineItemDouble.example(quantity: @quantity)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.example(options = {})
|
76
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class PartLineItemDouble
|
81
|
+
DEFAULT_OPTIONS = {
|
82
|
+
id: 444555,
|
83
|
+
variant: VariantDouble.example,
|
84
|
+
line_item: LineItemDouble.example
|
85
|
+
}
|
86
|
+
|
87
|
+
attr_reader :id, :variant, :line_item
|
88
|
+
def initialize(options = {})
|
89
|
+
@id = options[:id]
|
90
|
+
@variant = options[:variant]
|
91
|
+
@line_item = options[:line_item]
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.example(options = {})
|
95
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class StateDouble
|
100
|
+
DEFAULT_OPTIONS = {
|
101
|
+
iso_name: "CANADA",
|
102
|
+
name: "Ontario",
|
103
|
+
abbr: "ON",
|
104
|
+
}
|
105
|
+
|
106
|
+
attr_reader :name
|
107
|
+
|
108
|
+
def initialize(options = {})
|
109
|
+
@name = options[:name]
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.example(options = {})
|
113
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class CountryDouble
|
118
|
+
DEFAULT_OPTIONS = {
|
119
|
+
iso_name: "CANADA",
|
120
|
+
name: "Canada",
|
121
|
+
iso: "CA"
|
122
|
+
}
|
123
|
+
|
124
|
+
attr_reader :name
|
125
|
+
|
126
|
+
def initialize(options = {})
|
127
|
+
@name = options[:name]
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.example(options = {})
|
131
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
class AddressDouble
|
137
|
+
DEFAULT_OPTIONS = {
|
138
|
+
company: 'Shopify',
|
139
|
+
name: 'John Smith',
|
140
|
+
address1: '123 Fake St',
|
141
|
+
address2: 'Unit 128',
|
142
|
+
city: 'Ottawa',
|
143
|
+
country: CountryDouble.example,
|
144
|
+
state: StateDouble.example,
|
145
|
+
zipcode: 'K1N 5T5'
|
146
|
+
}
|
147
|
+
|
148
|
+
attr_reader :company, :name, :address1, :address2, :city, :country, :state, :zipcode
|
149
|
+
|
150
|
+
def initialize(options = {})
|
151
|
+
@company = options[:company]
|
152
|
+
@name = options[:name]
|
153
|
+
@address1 = options[:address1]
|
154
|
+
@address2 = options[:address2]
|
155
|
+
@city = options[:city]
|
156
|
+
@country = options[:country]
|
157
|
+
@state = options[:state]
|
158
|
+
@zipcode = options[:zipcode]
|
159
|
+
end
|
160
|
+
|
161
|
+
def full_name
|
162
|
+
name
|
163
|
+
end
|
164
|
+
|
165
|
+
def self.example(options = {})
|
166
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
class ShippingLineDouble
|
171
|
+
def initialize(options = {})
|
172
|
+
@options = options
|
173
|
+
end
|
174
|
+
|
175
|
+
def carrier
|
176
|
+
@options[:code].split('_').first
|
177
|
+
end
|
178
|
+
|
179
|
+
def service_level
|
180
|
+
@options[:code].split('_').last
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class ShippingMethodDouble
|
185
|
+
DEFAULT_OPTIONS = {
|
186
|
+
name: "UPS Ground",
|
187
|
+
admin_name: "fed001",
|
188
|
+
code: "fedex",
|
189
|
+
carrier: "FEDEX",
|
190
|
+
service_level: "GROUND"
|
191
|
+
}
|
192
|
+
|
193
|
+
attr_reader :name, :admin_name, :code, :carrier, :service_level
|
194
|
+
|
195
|
+
def initialize(options = {})
|
196
|
+
@name = options[:name]
|
197
|
+
@admin_name = options[:admin_name]
|
198
|
+
@code = options[:code]
|
199
|
+
@carrier = options[:carrier]
|
200
|
+
@service_level = options[:service_level]
|
201
|
+
end
|
202
|
+
|
203
|
+
def self.example(options = {})
|
204
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class OrderDouble
|
209
|
+
DEFAULT_OPTIONS = {
|
210
|
+
number: "GLO#{rand.to_s[2..11]}",
|
211
|
+
line_items: [LineItemDouble.example],
|
212
|
+
ship_address: AddressDouble.example,
|
213
|
+
bill_address: AddressDouble.example,
|
214
|
+
note: 'Happy Birthday',
|
215
|
+
created_at: Time.new(2013, 04, 05, 12, 30, 00),
|
216
|
+
id: 123456,
|
217
|
+
email: 'john@smith.com',
|
218
|
+
total_price: '123.45'
|
219
|
+
}
|
220
|
+
|
221
|
+
attr_reader :line_items, :ship_address, :bill_address, :note, :email
|
222
|
+
attr_reader :total_price, :email, :id, :type, :created_at, :shipping_lines
|
223
|
+
attr_reader :number
|
224
|
+
|
225
|
+
def initialize(options = {})
|
226
|
+
@line_items = options[:line_items]
|
227
|
+
@ship_address = options[:ship_address]
|
228
|
+
@bill_address = options[:bill_address]
|
229
|
+
@note = options[:note]
|
230
|
+
@created_at = options[:created_at]
|
231
|
+
@id = options[:id]
|
232
|
+
@shipping_lines = options[:shipping_lines]
|
233
|
+
@email = options[:email]
|
234
|
+
@total_price = options[:total_price]
|
235
|
+
@number = options[:number]
|
236
|
+
end
|
237
|
+
|
238
|
+
def self.example(options = {})
|
239
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
240
|
+
end
|
241
|
+
|
242
|
+
def special_instructions
|
243
|
+
@note
|
244
|
+
end
|
245
|
+
|
246
|
+
def shipping_address
|
247
|
+
@ship_address
|
248
|
+
end
|
249
|
+
|
250
|
+
def billing_address
|
251
|
+
@bill_address
|
252
|
+
end
|
253
|
+
|
254
|
+
def type
|
255
|
+
@type || "SO"
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class ShipmentDouble
|
260
|
+
DEFAULT_OPTIONS = {
|
261
|
+
shipping_method: ShippingMethodDouble.example,
|
262
|
+
number: "H#{rand.to_s[2..11]}",
|
263
|
+
order: OrderDouble.example,
|
264
|
+
address: AddressDouble.example,
|
265
|
+
state: "pending",
|
266
|
+
created_at: Time.new(2013, 04, 06, 13, 45, 00)
|
267
|
+
}
|
268
|
+
|
269
|
+
attr_reader :order, :number, :address, :shipping_method, :created_at
|
270
|
+
|
271
|
+
def initialize(options = {})
|
272
|
+
@order = options[:order]
|
273
|
+
@number = options[:number]
|
274
|
+
@address = options[:address]
|
275
|
+
@shipping_method = options[:shipping_method]
|
276
|
+
@created_at = options[:created_at]
|
277
|
+
end
|
278
|
+
|
279
|
+
def self.example(options = {})
|
280
|
+
self.new(DEFAULT_OPTIONS.merge(options))
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
class DocumentDouble
|
285
|
+
include Gentle::Documents::Document
|
286
|
+
attr_accessor :type, :message_id, :warehouse, :date, :client
|
287
|
+
attr_accessor :business_unit, :document_number, :io
|
288
|
+
|
289
|
+
def initialize(options = {})
|
290
|
+
options.each do |key, value|
|
291
|
+
self.public_send("#{key}=".to_sym, value)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def to_xml
|
296
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
297
|
+
xml.DocumentDouble 'Hello World'
|
298
|
+
end
|
299
|
+
builder.to_xml
|
300
|
+
end
|
301
|
+
|
302
|
+
def filename=(filename)
|
303
|
+
@filename = filename
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class MessageDouble
|
308
|
+
attr_accessor :document_name, :document_type
|
309
|
+
|
310
|
+
def initialize(options = {})
|
311
|
+
@document_name = options[:document_name]
|
312
|
+
@document_type = options[:document_type]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
class ClientDouble
|
317
|
+
attr_accessor :client_id, :business_unit
|
318
|
+
|
319
|
+
def initialize(options = {})
|
320
|
+
@client_id = options[:client_id]
|
321
|
+
@business_unit = options[:business_unit]
|
322
|
+
end
|
323
|
+
end
|