gentle 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.
- 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
|