kschadeck-active_shipping 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +38 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +126 -0
- data/lib/active_shipping.rb +50 -0
- data/lib/active_shipping/shipping/base.rb +13 -0
- data/lib/active_shipping/shipping/carrier.rb +81 -0
- data/lib/active_shipping/shipping/carriers.rb +20 -0
- data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +16 -0
- data/lib/active_shipping/shipping/carriers/canada_post.rb +261 -0
- data/lib/active_shipping/shipping/carriers/fedex.rb +372 -0
- data/lib/active_shipping/shipping/carriers/kunaki.rb +165 -0
- data/lib/active_shipping/shipping/carriers/new_zealand_post.rb +269 -0
- data/lib/active_shipping/shipping/carriers/shipwire.rb +178 -0
- data/lib/active_shipping/shipping/carriers/ups.rb +452 -0
- data/lib/active_shipping/shipping/carriers/usps.rb +441 -0
- data/lib/active_shipping/shipping/location.rb +149 -0
- data/lib/active_shipping/shipping/package.rb +147 -0
- data/lib/active_shipping/shipping/rate_estimate.rb +62 -0
- data/lib/active_shipping/shipping/rate_response.rb +19 -0
- data/lib/active_shipping/shipping/response.rb +46 -0
- data/lib/active_shipping/shipping/shipment_event.rb +14 -0
- data/lib/active_shipping/shipping/shipment_packer.rb +48 -0
- data/lib/active_shipping/shipping/tracking_response.rb +47 -0
- data/lib/active_shipping/version.rb +3 -0
- data/lib/certs/eParcel.dtd +111 -0
- data/lib/vendor/quantified/MIT-LICENSE +22 -0
- data/lib/vendor/quantified/README.markdown +49 -0
- data/lib/vendor/quantified/Rakefile +21 -0
- data/lib/vendor/quantified/init.rb +0 -0
- data/lib/vendor/quantified/lib/quantified.rb +6 -0
- data/lib/vendor/quantified/lib/quantified/attribute.rb +208 -0
- data/lib/vendor/quantified/lib/quantified/length.rb +20 -0
- data/lib/vendor/quantified/lib/quantified/mass.rb +19 -0
- data/lib/vendor/quantified/test/length_test.rb +92 -0
- data/lib/vendor/quantified/test/mass_test.rb +88 -0
- data/lib/vendor/quantified/test/test_helper.rb +10 -0
- data/lib/vendor/test_helper.rb +7 -0
- data/lib/vendor/xml_node/README +36 -0
- data/lib/vendor/xml_node/Rakefile +21 -0
- data/lib/vendor/xml_node/benchmark/bench_generation.rb +32 -0
- data/lib/vendor/xml_node/init.rb +1 -0
- data/lib/vendor/xml_node/lib/xml_node.rb +222 -0
- data/lib/vendor/xml_node/test/test_generating.rb +94 -0
- data/lib/vendor/xml_node/test/test_parsing.rb +43 -0
- metadata +233 -0
@@ -0,0 +1,147 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping #:nodoc:
|
3
|
+
class Package
|
4
|
+
include Quantified
|
5
|
+
|
6
|
+
cattr_accessor :default_options
|
7
|
+
attr_reader :options, :value, :currency
|
8
|
+
|
9
|
+
# Package.new(100, [10, 20, 30], :units => :metric)
|
10
|
+
# Package.new(Mass.new(100, :grams), [10, 20, 30].map {|m| Length.new(m, :centimetres)})
|
11
|
+
# Package.new(100.grams, [10, 20, 30].map(&:centimetres))
|
12
|
+
def initialize(grams_or_ounces, dimensions, options = {})
|
13
|
+
options = @@default_options.update(options) if @@default_options
|
14
|
+
options.symbolize_keys!
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
@dimensions = [dimensions].flatten.reject {|d| d.nil?}
|
18
|
+
|
19
|
+
imperial = (options[:units] == :imperial) ||
|
20
|
+
([grams_or_ounces, *dimensions].all? {|m| m.respond_to?(:unit) && m.unit.to_sym == :imperial})
|
21
|
+
|
22
|
+
@unit_system = imperial ? :imperial : :metric
|
23
|
+
|
24
|
+
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Mass, :grams, :ounces)
|
25
|
+
|
26
|
+
if @dimensions.blank?
|
27
|
+
@dimensions = [Length.new(0, (imperial ? :inches : :centimetres))] * 3
|
28
|
+
else
|
29
|
+
process_dimensions
|
30
|
+
end
|
31
|
+
|
32
|
+
@value = Package.cents_from(options[:value])
|
33
|
+
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
|
34
|
+
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
|
35
|
+
@gift = options[:gift] ? true : false
|
36
|
+
end
|
37
|
+
|
38
|
+
def cylinder?
|
39
|
+
@cylinder
|
40
|
+
end
|
41
|
+
alias_method :tube?, :cylinder?
|
42
|
+
|
43
|
+
def gift?; @gift end
|
44
|
+
|
45
|
+
def ounces(options={})
|
46
|
+
weight(options).in_ounces.amount
|
47
|
+
end
|
48
|
+
alias_method :oz, :ounces
|
49
|
+
|
50
|
+
def grams(options={})
|
51
|
+
weight(options).in_grams.amount
|
52
|
+
end
|
53
|
+
alias_method :g, :grams
|
54
|
+
|
55
|
+
def pounds(options={})
|
56
|
+
weight(options).in_pounds.amount
|
57
|
+
end
|
58
|
+
alias_method :lb, :pounds
|
59
|
+
alias_method :lbs, :pounds
|
60
|
+
|
61
|
+
def kilograms(options={})
|
62
|
+
weight(options).in_kilograms.amount
|
63
|
+
end
|
64
|
+
alias_method :kg, :kilograms
|
65
|
+
alias_method :kgs, :kilograms
|
66
|
+
|
67
|
+
def inches(measurement=nil)
|
68
|
+
@inches ||= @dimensions.map {|m| m.in_inches.amount }
|
69
|
+
measurement.nil? ? @inches : measure(measurement, @inches)
|
70
|
+
end
|
71
|
+
alias_method :in, :inches
|
72
|
+
|
73
|
+
def centimetres(measurement=nil)
|
74
|
+
@centimetres ||= @dimensions.map {|m| m.in_centimetres.amount }
|
75
|
+
measurement.nil? ? @centimetres : measure(measurement, @centimetres)
|
76
|
+
end
|
77
|
+
alias_method :cm, :centimetres
|
78
|
+
|
79
|
+
def weight(options = {})
|
80
|
+
case options[:type]
|
81
|
+
when nil, :actual
|
82
|
+
@weight
|
83
|
+
when :volumetric, :dimensional
|
84
|
+
@volumetric_weight ||= begin
|
85
|
+
m = Mass.new((centimetres(:box_volume) / 6.0), :grams)
|
86
|
+
@unit_system == :imperial ? m.in_ounces : m
|
87
|
+
end
|
88
|
+
when :billable
|
89
|
+
[ weight, weight(:type => :volumetric) ].max
|
90
|
+
end
|
91
|
+
end
|
92
|
+
alias_method :mass, :weight
|
93
|
+
|
94
|
+
def self.cents_from(money)
|
95
|
+
return nil if money.nil?
|
96
|
+
if money.respond_to?(:cents)
|
97
|
+
return money.cents
|
98
|
+
else
|
99
|
+
case money
|
100
|
+
when Float
|
101
|
+
(money * 100).round
|
102
|
+
when String
|
103
|
+
money =~ /\./ ? (money.to_f * 100).round : money.to_i
|
104
|
+
else
|
105
|
+
money.to_i
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def attribute_from_metric_or_imperial(obj, klass, metric_unit, imperial_unit)
|
113
|
+
if obj.is_a?(klass)
|
114
|
+
return value
|
115
|
+
else
|
116
|
+
return klass.new(obj, (@unit_system == :imperial ? imperial_unit : metric_unit))
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def measure(measurement, ary)
|
121
|
+
case measurement
|
122
|
+
when Fixnum then ary[measurement]
|
123
|
+
when :x, :max, :length, :long then ary[2]
|
124
|
+
when :y, :mid, :width, :wide then ary[1]
|
125
|
+
when :z, :min, :height,:depth,:high,:deep then ary[0]
|
126
|
+
when :girth, :around,:circumference
|
127
|
+
self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 2) : (2 * ary[0]) + (2 * ary[1])
|
128
|
+
when :volume then self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume,ary)
|
129
|
+
when :box_volume then ary[0] * ary[1] * ary[2]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def process_dimensions
|
134
|
+
@dimensions = @dimensions.map do |l|
|
135
|
+
attribute_from_metric_or_imperial(l, Length, :centimetres, :inches)
|
136
|
+
end.sort
|
137
|
+
# [1,2] => [1,1,2]
|
138
|
+
# [5] => [5,5,5]
|
139
|
+
# etc..
|
140
|
+
2.downto(@dimensions.length) do |n|
|
141
|
+
@dimensions.unshift(@dimensions[0])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping #:nodoc:
|
3
|
+
|
4
|
+
class RateEstimate
|
5
|
+
attr_reader :origin # Location objects
|
6
|
+
attr_reader :destination
|
7
|
+
attr_reader :package_rates # array of hashes in the form of {:package => <Package>, :rate => 500}
|
8
|
+
attr_reader :carrier # Carrier.name ('USPS', 'FedEx', etc.)
|
9
|
+
attr_reader :service_name # name of service ("First Class Ground", etc.)
|
10
|
+
attr_reader :service_code
|
11
|
+
attr_reader :currency # 'USD', 'CAD', etc.
|
12
|
+
# http://en.wikipedia.org/wiki/ISO_4217
|
13
|
+
attr_reader :delivery_date # Usually only available for express shipments
|
14
|
+
attr_reader :delivery_range # Min and max delivery estimate in days
|
15
|
+
|
16
|
+
def initialize(origin, destination, carrier, service_name, options={})
|
17
|
+
@origin, @destination, @carrier, @service_name = origin, destination, carrier, service_name
|
18
|
+
@service_code = options[:service_code]
|
19
|
+
if options[:package_rates]
|
20
|
+
@package_rates = options[:package_rates].map {|p| p.update({:rate => Package.cents_from(p[:rate])}) }
|
21
|
+
else
|
22
|
+
@package_rates = Array(options[:packages]).map {|p| {:package => p}}
|
23
|
+
end
|
24
|
+
@total_price = Package.cents_from(options[:total_price])
|
25
|
+
@currency = options[:currency]
|
26
|
+
@delivery_range = options[:delivery_range] ? options[:delivery_range].map { |date| date_for(date) }.compact : []
|
27
|
+
@delivery_date = @delivery_range.last
|
28
|
+
end
|
29
|
+
|
30
|
+
def total_price
|
31
|
+
begin
|
32
|
+
@total_price || @package_rates.sum {|p| p[:rate]}
|
33
|
+
rescue NoMethodError
|
34
|
+
raise ArgumentError.new("RateEstimate must have a total_price set, or have a full set of valid package rates.")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
alias_method :price, :total_price
|
38
|
+
|
39
|
+
def add(package,rate=nil)
|
40
|
+
cents = Package.cents_from(rate)
|
41
|
+
raise ArgumentError.new("New packages must have valid rate information since this RateEstimate has no total_price set.") if cents.nil? and total_price.nil?
|
42
|
+
@package_rates << {:package => package, :rate => cents}
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def packages
|
47
|
+
package_rates.map {|p| p[:package]}
|
48
|
+
end
|
49
|
+
|
50
|
+
def package_count
|
51
|
+
package_rates.length
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def date_for(date)
|
56
|
+
date && DateTime.strptime(date.to_s, "%Y-%m-%d")
|
57
|
+
rescue ArgumentError
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping
|
3
|
+
|
4
|
+
class RateResponse < Response
|
5
|
+
|
6
|
+
attr_reader :rates
|
7
|
+
|
8
|
+
def initialize(success, message, params = {}, options = {})
|
9
|
+
@rates = Array(options[:estimates] || options[:rates] || options[:rate_estimates])
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
alias_method :estimates, :rates
|
14
|
+
alias_method :rate_estimates, :rates
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
|
3
|
+
module Shipping #:nodoc:
|
4
|
+
|
5
|
+
class Error < ActiveMerchant::ActiveMerchantError
|
6
|
+
end
|
7
|
+
|
8
|
+
class ResponseError < Error
|
9
|
+
attr_reader :response
|
10
|
+
|
11
|
+
def initialize(response = nil)
|
12
|
+
if response.is_a? Response
|
13
|
+
super(response.message)
|
14
|
+
@response = response
|
15
|
+
else
|
16
|
+
super(response)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Response
|
22
|
+
|
23
|
+
attr_reader :params
|
24
|
+
attr_reader :message
|
25
|
+
attr_reader :test
|
26
|
+
attr_reader :xml
|
27
|
+
attr_reader :request
|
28
|
+
|
29
|
+
def initialize(success, message, params = {}, options = {})
|
30
|
+
@success, @message, @params = success, message, params.stringify_keys
|
31
|
+
@test = options[:test] || false
|
32
|
+
@xml = options[:xml]
|
33
|
+
@request = options[:request]
|
34
|
+
raise ResponseError.new(self) unless success
|
35
|
+
end
|
36
|
+
|
37
|
+
def success?
|
38
|
+
@success ? true : false
|
39
|
+
end
|
40
|
+
|
41
|
+
def test?
|
42
|
+
@test ? true : false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping
|
3
|
+
|
4
|
+
class ShipmentEvent
|
5
|
+
attr_reader :name, :time, :location, :message
|
6
|
+
|
7
|
+
def initialize(name, time, location, message=nil)
|
8
|
+
@name, @time, @location, @message = name, time, location, message
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ActiveMerchant
|
2
|
+
module Shipping
|
3
|
+
class ShipmentPacker
|
4
|
+
class OverweightItem < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
# items - array of hashes containing quantity, grams and price.
|
8
|
+
# ex. [{:quantity => 2, :price => 1.0, :grams => 50}]
|
9
|
+
# dimensions - [5.0, 15.0, 30.0]
|
10
|
+
# maximum_weight - maximum weight in grams
|
11
|
+
# currency - ISO currency code
|
12
|
+
def self.pack(items, dimensions, maximum_weight, currency)
|
13
|
+
items = items.map(&:symbolize_keys).map { |item| [item] * item[:quantity].to_i }.flatten
|
14
|
+
packages = []
|
15
|
+
state = :package_empty
|
16
|
+
|
17
|
+
while state != :packing_finished
|
18
|
+
case state
|
19
|
+
when :package_empty
|
20
|
+
package_weight, package_value = 0, 0
|
21
|
+
state = :filling_package
|
22
|
+
when :filling_package
|
23
|
+
item = items.shift
|
24
|
+
item_weight, item_price = item[:grams].to_i, Package.cents_from(item[:price])
|
25
|
+
|
26
|
+
if item_weight > maximum_weight
|
27
|
+
raise OverweightItem, "The item with weight of #{item_weight}g is heavier than the allowable package weight of #{maximum_weight}g"
|
28
|
+
end
|
29
|
+
|
30
|
+
if (package_weight + item_weight) <= maximum_weight
|
31
|
+
package_weight += item_weight
|
32
|
+
package_value += item_price
|
33
|
+
state = :package_full if items.empty?
|
34
|
+
else
|
35
|
+
items.unshift(item)
|
36
|
+
state = :package_full
|
37
|
+
end
|
38
|
+
when :package_full
|
39
|
+
packages << ActiveMerchant::Shipping::Package.new(package_weight, dimensions, :value => package_value, :currency => currency)
|
40
|
+
state = items.any? ? :package_empty : :packing_finished
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
packages
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping
|
3
|
+
|
4
|
+
class TrackingResponse < Response
|
5
|
+
attr_reader :carrier # symbol
|
6
|
+
attr_reader :carrier_name # string
|
7
|
+
attr_reader :status # symbol
|
8
|
+
attr_reader :status_code # string
|
9
|
+
attr_reader :status_description #string
|
10
|
+
attr_reader :scheduled_delivery_date # time
|
11
|
+
attr_reader :tracking_number # string
|
12
|
+
attr_reader :shipment_events # array of ShipmentEvents in chronological order
|
13
|
+
attr_reader :origin, :destination
|
14
|
+
|
15
|
+
def initialize(success, message, params = {}, options = {})
|
16
|
+
@carrier = options[:carrier].parameterize.to_sym
|
17
|
+
@carrier_name = options[:carrier]
|
18
|
+
@status = options[:status]
|
19
|
+
@status_code = options[:status_code]
|
20
|
+
@status_description = options[:status_description]
|
21
|
+
@scheduled_delivery_date = options[:scheduled_delivery_date]
|
22
|
+
@tracking_number = options[:tracking_number]
|
23
|
+
@shipment_events = Array(options[:shipment_events])
|
24
|
+
@origin, @destination = options[:origin], options[:destination]
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def latest_event
|
29
|
+
@shipment_events.last
|
30
|
+
end
|
31
|
+
|
32
|
+
def is_delivered?
|
33
|
+
@status == :delivered
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_exception?
|
37
|
+
@status == :exception
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method(:exception_event, :latest_event)
|
41
|
+
alias_method(:delivered?, :is_delivered?)
|
42
|
+
alias_method(:exception?, :has_exception?)
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
|
2
|
+
<!ELEMENT eparcel (language?,
|
3
|
+
( ratesAndServicesRequest |
|
4
|
+
ratesAndServicesResponse |
|
5
|
+
error
|
6
|
+
)+)>
|
7
|
+
|
8
|
+
<!ELEMENT language (#PCDATA)>
|
9
|
+
<!ELEMENT comment (#PCDATA)>
|
10
|
+
|
11
|
+
|
12
|
+
<!-- Standard request to ask for rates and services -->
|
13
|
+
<!ELEMENT ratesAndServicesRequest ( merchantCPCID,
|
14
|
+
fromPostalCode?,
|
15
|
+
turnAroundTime?,
|
16
|
+
itemsPrice?,
|
17
|
+
lineItems,
|
18
|
+
city?,
|
19
|
+
provOrState,
|
20
|
+
country,
|
21
|
+
postalCode)>
|
22
|
+
<!ELEMENT merchantID (#PCDATA)>
|
23
|
+
<!ELEMENT fromPostalCode (#PCDATA)>
|
24
|
+
<!ELEMENT turnAroundTime (#PCDATA)>
|
25
|
+
<!ELEMENT itemsPrice (#PCDATA)>
|
26
|
+
<!ELEMENT merchantCPCID (#PCDATA)>
|
27
|
+
<!ELEMENT lineItems (item)+>
|
28
|
+
<!ELEMENT item (quantity, weight, length, width, height, description, imageURL?, readyToShip)>
|
29
|
+
<!ELEMENT quantity (#PCDATA)>
|
30
|
+
<!ELEMENT weight (#PCDATA)>
|
31
|
+
<!ELEMENT length (#PCDATA)>
|
32
|
+
<!ELEMENT width (#PCDATA)>
|
33
|
+
<!ELEMENT height (#PCDATA)>
|
34
|
+
<!ELEMENT description (#PCDATA)>
|
35
|
+
<!ELEMENT imageURL (#PCDATA)>
|
36
|
+
<!ELEMENT readyToShip (#PCDATA)>
|
37
|
+
<!ELEMENT city (#PCDATA)>
|
38
|
+
<!ELEMENT provOrState (#PCDATA)>
|
39
|
+
<!ELEMENT country (#PCDATA)>
|
40
|
+
<!ELEMENT postalCode (#PCDATA)>
|
41
|
+
|
42
|
+
<!-- Standard response for request for rates and services -->
|
43
|
+
<!ELEMENT ratesAndServicesResponse (statusCode,
|
44
|
+
statusMessage+,
|
45
|
+
requestID,
|
46
|
+
handling,
|
47
|
+
language,
|
48
|
+
product+,
|
49
|
+
packing*,
|
50
|
+
emptySpace*,
|
51
|
+
shippingOptions,
|
52
|
+
comment,
|
53
|
+
nearestPostalOutlet*)>
|
54
|
+
|
55
|
+
<!ELEMENT statusCode (#PCDATA)>
|
56
|
+
<!ELEMENT statusMessage (#PCDATA)>
|
57
|
+
<!ELEMENT requestID (#PCDATA)>
|
58
|
+
<!ELEMENT handling (#PCDATA)>
|
59
|
+
|
60
|
+
<!ELEMENT product (name, rate, shippingDate, deliveryDate, deliveryDayOfWeek, nextDayAM?, packingID)>
|
61
|
+
<!ATTLIST product id CDATA #REQUIRED>
|
62
|
+
<!ATTLIST product sequence CDATA #REQUIRED>
|
63
|
+
<!ELEMENT name (#PCDATA)>
|
64
|
+
<!ELEMENT rate (#PCDATA)>
|
65
|
+
<!ELEMENT shippingDate (#PCDATA)>
|
66
|
+
<!ELEMENT deliveryDate (#PCDATA)>
|
67
|
+
<!ELEMENT deliveryDayOfWeek (#PCDATA)>
|
68
|
+
<!ELEMENT nextDayAM (#PCDATA)>
|
69
|
+
<!ELEMENT packingID (#PCDATA)>
|
70
|
+
|
71
|
+
<!ELEMENT packing (packingID, box+)>
|
72
|
+
<!ELEMENT box (name, weight, expediterWeight, length, width, height, packedItem+)>
|
73
|
+
<!ELEMENT expediterWeight (#PCDATA)>
|
74
|
+
<!ELEMENT packedItem (quantity, description)>
|
75
|
+
|
76
|
+
<!ELEMENT emptySpace (length, width, height, weight)>
|
77
|
+
|
78
|
+
<!ELEMENT shippingOptions (insurance, deliveryConfirmation, signature)>
|
79
|
+
<!ELEMENT insurance (#PCDATA)>
|
80
|
+
<!ELEMENT deliveryConfirmation (#PCDATA)>
|
81
|
+
<!ELEMENT signature (#PCDATA)>
|
82
|
+
|
83
|
+
|
84
|
+
<!-- ********************************************************* -->
|
85
|
+
<!-- * 'nearestPostalOutlet' is optional and is returned * -->
|
86
|
+
<!-- * only if the merchant profile has this option enabled * -->
|
87
|
+
<!-- ********************************************************* -->
|
88
|
+
<!ELEMENT nearestPostalOutlet (postalOutletSequenceNo,
|
89
|
+
distance,
|
90
|
+
outletName,
|
91
|
+
businessName ,
|
92
|
+
postalAddress,
|
93
|
+
phoneNumber,
|
94
|
+
businessHours+)>
|
95
|
+
<!ELEMENT postalOutletSequenceNo (#PCDATA)>
|
96
|
+
<!ELEMENT distance (#PCDATA)>
|
97
|
+
<!ELEMENT outletName (#PCDATA)>
|
98
|
+
<!ELEMENT businessName (#PCDATA)>
|
99
|
+
<!ELEMENT postalAddress (addressLine+, postalCode , municipality)>
|
100
|
+
<!ELEMENT addressLine (#PCDATA)>
|
101
|
+
<!ELEMENT municipality (#PCDATA)>
|
102
|
+
<!ELEMENT phoneNumber (#PCDATA)>
|
103
|
+
<!ELEMENT businessHours (dayId, dayOfWeek, time)>
|
104
|
+
<!ELEMENT dayId (#PCDATA)>
|
105
|
+
<!ELEMENT dayOfWeek (#PCDATA)>
|
106
|
+
<!ELEMENT time (#PCDATA)>
|
107
|
+
|
108
|
+
|
109
|
+
<!-- Standard error format returned -->
|
110
|
+
<!ELEMENT error (statusCode,statusMessage*)>
|
111
|
+
|