dhl-bcs 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 266d8258d3a8678be51463d1148afd001473943e
4
- data.tar.gz: a9feb88be17f8acf306b66363fc869aae592f919
2
+ SHA256:
3
+ metadata.gz: '08009611f405006ad59d2fac8990162898692cab2f7e02f4f7840327b64204fe'
4
+ data.tar.gz: 31e0b88042b710331d0b96a177ef42977c656b165d319ccf309cc87b81ed69eb
5
5
  SHA512:
6
- metadata.gz: c5863fa920acf37223595ef5c16b5f779e2b2505f91abc9c6895d1abc895a020c85d18ac8023ab76a853ed11402bd3d65c1b0d82320bc9cdcfbabde5e7fe8f6f
7
- data.tar.gz: 314a2e6fe4ecebbb1a47f933ac82af1d8b102bb82852906f9de2ea06be728e3e67a38d5f02253896fbbc18de489e299542d3dadc6eb577a160772848d04248f1
6
+ metadata.gz: 349f7a9c8cc4675ad17b9703eaf09894982ba97882f5159081f6b6184570226ee2a491720c4bc716d1fd600f2389d17a971e72c7041dc1d30ef0e85d31f390ae
7
+ data.tar.gz: c4060bd137c262e0ab29fff8eb45e93a93ba843fd1bd7ceccbd12b27231c226f53c81621e1c6c33fac8be1d88c7982bd20f2b06b54dce9912721a9ba3b14efa0
data/README.md CHANGED
@@ -148,6 +148,59 @@ shipment3 = Dhl::Bcs.build_shipment(shipper: shipper, receiver: receiver, weight
148
148
 
149
149
  client.create_shipment_order(shipment1, shipment2, shipment3)
150
150
  ```
151
+ ### International Shipments
152
+
153
+ In order to send parcels outside of the EU, one should provide information about the content of the shipment.
154
+ Dhl offers cn23 document, which is data for the Customs as this kind of shipment is considered Export of goods.
155
+ As an output one gets, in addition to the label, a url for the document in an A4-format ready to be printed.
156
+
157
+ The way to implement that is identical of shipper's and receiver's ones.
158
+
159
+ ```ruby
160
+ export_document = {
161
+ invoice_number = 'ABCDEF...',
162
+ export_type = 'Document', # could be one of these ['RETURN_OF_GOODS','PRESENT','COMMERCIAL_SAMPLE','DOCUMENT','OTHER']
163
+ export_type_description = 'some desc', # should be set if `export_type` was set to 'OTHER'
164
+ terms_of_trade = 'DDP', # could be one of these ['DDP','DXV','DDU','DDX']
165
+ place_of_commital= 'Bern',
166
+ permit_number = 1232135,
167
+ attestation_number = 1234345,
168
+ with_electronic_export_notification = true, # true|false
169
+ export_doc_positions: [
170
+ {
171
+ description: 'content1',
172
+ country_code_origing: 'CN',
173
+ customs_tariff_number: '1234567',
174
+ ammount: 1,
175
+ net_weight_in_kg: 0.2,
176
+ customs_value: 25.00
177
+ },
178
+ {
179
+ description: 'content2',
180
+ country_code_origing: 'DE',
181
+ customs_tariff_number: '00222011',
182
+ ammount: 1,
183
+ net_weight_in_kg: 1.2,
184
+ customs_value: 112.00
185
+ }
186
+ ]
187
+ }
188
+
189
+ shipment = Dhl::Bcs.build_shipment(export_document: export_document, shipper: shipper, receiver: receiver)
190
+ ```
191
+
192
+ and then one gets a result like this:
193
+
194
+ ```ruby
195
+ [
196
+ {
197
+ status: { status_code: '0', status_text: 'ok', status_message: 'Der Webservice wurde ohne Fehler ausgeführt.' },
198
+ shipment_number: '22222222201019582121',
199
+ label_url: 'https://cig.dhl.de/gkvlabel/SANDBOX/dhl-vls/gw/shpmntws/printShipment?token=JD7HKktuvugIFEkhSvCfbEz4J8Ah0dkcVuw4PzBGRyRnW%2FwEPAwfytLtb31e7gMDsSX32%2BEB5exp8nNPs%2FhJSQ%3D%3D',
200
+ export_label_url: 'https://cig.dhl.de/gkvlabel/SANDBOX/dhl-vls/gw/shpmntws/printShipment?token=Vfov%2BMinVhMH6nQVfvSCmNUSRNnaQNHKPaiLiWtXsqm%2BENCM6wnStB2C44rl6BEmSxbrPeaTQwBhoHBr802FnuftGVJ9uVM0C0ztLpxNfyc%3D',
201
+ }
202
+ ]
203
+ ```
151
204
 
152
205
  ### Validate shipments
153
206
 
@@ -19,11 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "savon", "~> 2.11"
22
+ spec.add_dependency "savon", "~> 2.12"
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.15"
25
- spec.add_development_dependency "rake", "~> 12.0"
26
- spec.add_development_dependency "minitest", "~> 5.10"
27
- spec.add_development_dependency "webmock", "~> 3.0"
28
- spec.add_development_dependency "pry-byebug", "~> 3.4"
24
+ spec.add_development_dependency "bundler", "~> 1.16"
25
+ spec.add_development_dependency "rake", "~> 12.3"
26
+ spec.add_development_dependency "minitest", "~> 5.11"
27
+ spec.add_development_dependency "webmock", "~> 3.3"
28
+ spec.add_development_dependency "pry-byebug", "~> 3.6"
29
29
  end
@@ -13,6 +13,8 @@ require 'dhl/bcs/v2/parcel_shop'
13
13
  require 'dhl/bcs/v2/postfiliale'
14
14
  require 'dhl/bcs/v2/bank_data'
15
15
  require 'dhl/bcs/v2/service'
16
+ require 'dhl/bcs/v2/locator'
17
+ require 'dhl/bcs/v2/export_document'
16
18
 
17
19
  module Dhl
18
20
  module Bcs
@@ -0,0 +1,84 @@
1
+ module Dhl::Bcs::V2
2
+ class ExportDocument
3
+ include Buildable
4
+
5
+ PROPERTIES = %i(invoice_number export_type export_type_description terms_of_trade place_of_commital additional_fee permit_number attestation_number with_electronic_export_notification export_doc_positions).freeze
6
+ attr_accessor(*PROPERTIES)
7
+
8
+ EXPORT_TYPES = %w(OTHER PRESENT COMMERCIAL_SAMPLE DOCUMENT RETURN_OF_GOODS).freeze
9
+ TERMS_OF_TRADES = %w(DDP DXV DDU DDX).freeze
10
+
11
+ def self.build(export_doc_positions = [], **attributes)
12
+ array_of_export_doc_positions = []
13
+ export_doc_positions.each do |export_doc_position|
14
+ array_of_export_doc_positions << ExportDocPosition.build(export_doc_position) if export_doc_position.is_a?(Hash)
15
+ end
16
+ new({ export_doc_positions: array_of_export_doc_positions }.merge(attributes))
17
+ end
18
+
19
+ def initialize(**attributes)
20
+ attributes.each do |property, value|
21
+ send("#{property}=", value) if PROPERTIES.include?(property)
22
+ end
23
+ end
24
+
25
+ def export_type=(export_type)
26
+ raise Dhl::Bcs::Error, "No Valid export_type #{export_type}, Please use one of these: #{EXPORT_TYPES.join(',')}" unless EXPORT_TYPES.include?(export_type)
27
+ @export_type = export_type
28
+ end
29
+
30
+ def terms_of_trade=(terms_of_trade)
31
+ raise Dhl::Bcs::Error, "No Valid terms_of_trade #{terms_of_trade}, Please use one of these: #{TERMS_OF_TRADES.join(',')}" unless TERMS_OF_TRADES.include?(terms_of_trade)
32
+ @terms_of_trade = terms_of_trade
33
+ end
34
+
35
+ def to_soap_hash
36
+ raise Dhl::Bcs::Error, "export_doc_position must be set as an array." unless export_doc_positions
37
+ raise Dhl::Bcs::Error, "export_type_desription must be set, as export_type is set to OTHER." unless !((export_type == 'OTHER') ^ export_type_description)
38
+ raise Dhl::Bcs::Error, "place_of_commital must be set" unless place_of_commital
39
+ h = {}
40
+ h['invoiceNumber'] = invoice_number if invoice_number
41
+ h['exportType'] = export_type
42
+ h['exportTypeDescription'] = export_type_description if export_type_description
43
+ h['termsOfTrade'] = terms_of_trade if terms_of_trade
44
+ h['placeOfCommital'] = place_of_commital
45
+ h['additionalFee'] = additional_fee if additional_fee
46
+ h['permitNumber'] = permit_number if permit_number
47
+ h['attestationNumber'] = attestation_number if attestation_number
48
+ h['WithElectronicExportNtfctn/'] = {'@active': 1} if with_electronic_export_notification
49
+ h['ExportDocPosition'] = self.export_doc_positions.map { |e| e.to_soap_hash }
50
+ h
51
+ end
52
+ end
53
+
54
+ class ExportDocPosition
55
+ PROPERTIES = %i(description country_code_origin customs_tariff_number amount net_weight_in_kg customs_value).freeze
56
+ attr_accessor(*PROPERTIES)
57
+
58
+ include Buildable
59
+
60
+ def initialize(**attributes)
61
+ attributes.each do |property, value|
62
+ send("#{property}=", value) if PROPERTIES.include?(property)
63
+ end
64
+ end
65
+
66
+ def to_soap_hash
67
+ raise Dhl::Bcs::Error, 'export doc position description must be set' unless description
68
+ raise Dhl::Bcs::Error, 'export doc position country_code_origin must be set' unless country_code_origin
69
+ raise Dhl::Bcs::Error, 'export doc position customs_tariff_number must be set' unless customs_tariff_number
70
+ raise Dhl::Bcs::Error, 'export doc position amount must be set' unless amount
71
+ raise Dhl::Bcs::Error, 'export doc position net_weight_in_kg must be set' unless net_weight_in_kg
72
+ raise Dhl::Bcs::Error, 'export doc position customs_value must be set' unless customs_value
73
+ {
74
+ 'description' => description,
75
+ 'countryCodeOrigin' => country_code_origin,
76
+ 'customsTariffNumber' => customs_tariff_number,
77
+ 'amount' => amount,
78
+ 'netWeightInKG' => net_weight_in_kg,
79
+ 'customsValue' => customs_value
80
+ }
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,27 @@
1
+ module Dhl::Bcs::V2
2
+ # finds proper class from attributes and builds object
3
+ class Locator
4
+
5
+ def self.for(attributes = {})
6
+ location_class = location_class_finder(attributes)
7
+ location_builder(attributes, location_class: location_class)
8
+ end
9
+
10
+ def self.location_class_finder(attributes)
11
+ if attributes.key?(:packstation_number)
12
+ Packstation
13
+ elsif attributes.key?(:postfilial_number)
14
+ Postfiliale
15
+ elsif attributes.key?(:parcel_shop_number)
16
+ ParcelShop
17
+ else
18
+ Address
19
+ end
20
+ end
21
+
22
+ def self.location_builder(attributes = {}, location_class: Address)
23
+ location_class.build(attributes)
24
+ end
25
+
26
+ end
27
+ end
@@ -8,16 +8,7 @@ module Dhl::Bcs::V2
8
8
 
9
9
  def self.build(name: nil, **attributes)
10
10
  communication = Communication.build(attributes)
11
- location =
12
- if attributes.key?(:packstation_number)
13
- Packstation
14
- elsif attributes.key?(:postfilial_number)
15
- Postfiliale
16
- elsif attributes.key?(:parcel_shop_number)
17
- ParcelShop
18
- else
19
- Address
20
- end.build(attributes)
11
+ location = Locator.for(attributes)
21
12
  new(attributes.merge(name: name, communication: communication, location: location))
22
13
  end
23
14
 
@@ -1,16 +1,20 @@
1
1
  module Dhl::Bcs::V2
2
2
  class Shipment
3
3
 
4
- attr_accessor :shipper, :receiver, :bank_data, :shipment_date, :product,
4
+ attr_accessor :shipper, :receiver, :bank_data, :shipment_date,
5
5
  :customer_reference, :services, :weight, :length, :height, :width,
6
- :notification_email
6
+ :notification_email, :export_document
7
+ attr_reader :product
7
8
 
8
9
  PRODUCT_PROCEDURE_NUMBERS = {
9
- 'V01PAK' => '01', # Paket National
10
- 'V53WPAK' => '53', # Weltpaket
11
- 'V54EPAK' => '54', # Europaket
12
- 'V06TG' => '01', # Kurier Taggleich
13
- 'V06WZ' => '01', # Kurier Wunschzeit
10
+ 'V01PAK' => '01', # DHL Paket
11
+ 'V01PRIO' => '01', # DHL Paket Prio
12
+ 'V06PAK' => '06', # DHL Paket Taggleich
13
+ 'V53WPAK' => '53', # DHL Paket International
14
+ 'V54EPAK' => '54', # DHL Europaket
15
+ 'V55PAK' => '55', # DHL Paket Connect
16
+ 'V06TG' => '01', # DHL Kurier Taggleich
17
+ 'V06WZ' => '01', # DHL Kurier Wunschzeit
14
18
  'V86PARCEL' => '86', # DHL Paket Austria
15
19
  'V87PARCEL' => '87', # DHL PAKET Connect
16
20
  'V82PARCEL' => '82' # DHL PAKET International
@@ -18,11 +22,12 @@ module Dhl::Bcs::V2
18
22
  PRODUCTS = PRODUCT_PROCEDURE_NUMBERS.keys.freeze
19
23
 
20
24
  # build a shipment from hash data
21
- def self.build(shipper:, receiver:, bank_data: nil, **shipment_attributes)
25
+ def self.build(shipper:, receiver:, bank_data: nil, export_document: nil, **shipment_attributes)
22
26
  shipper = Shipper.build(shipper) if shipper.is_a?(Hash)
23
27
  receiver = Receiver.build(receiver) if receiver.is_a?(Hash)
24
28
  bank_data = BankData.build(bank_data) if bank_data.is_a?(Hash)
25
- new({ shipper: shipper, receiver: receiver, bank_data: bank_data }.merge(shipment_attributes))
29
+ export_document = ExportDocument.build(export_document.delete(:export_doc_positions),export_document) if export_document.is_a?(Hash)
30
+ new({ shipper: shipper, receiver: receiver, bank_data: bank_data, export_document: export_document }.merge(shipment_attributes))
26
31
  end
27
32
 
28
33
  def initialize(attributes = {})
@@ -52,6 +57,7 @@ module Dhl::Bcs::V2
52
57
  raise Dhl::Bcs::Error, 'Sender address must be set!' unless shipper
53
58
  raise Dhl::Bcs::Error, 'Receiver address must be set!' unless receiver
54
59
  raise Dhl::Bcs::Error, 'Product must be set!' unless product
60
+ raise Dhl::Bcs::Error, 'In order to do an international shipment --product:V53WPAK--, :export_document muse be set!' unless !((product == 'V53WPAK') ^ export_document )
55
61
 
56
62
  account_number = "#{ekp}#{PRODUCT_PROCEDURE_NUMBERS[product]}#{participation_number}"
57
63
  raise Dhl::Bcs::Error, 'Need a 14 character long account number. Check EKP and participation_number' if account_number.size != 14
@@ -76,6 +82,9 @@ module Dhl::Bcs::V2
76
82
  'Shipper' => shipper.to_soap_hash,
77
83
  # Receiver information
78
84
  'Receiver' => receiver.to_soap_hash
85
+ }.tap{|h|
86
+ #ExportDocuemnt information
87
+ h['ExportDocument'] = export_document.to_soap_hash if export_document
79
88
  }
80
89
  end
81
90
 
@@ -1,5 +1,5 @@
1
1
  module Dhl
2
2
  module Bcs
3
- VERSION = "0.1.1"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dhl-bcs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christoph Wagner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-06 00:00:00.000000000 Z
11
+ date: 2018-05-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: savon
@@ -16,84 +16,84 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.11'
19
+ version: '2.12'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.11'
26
+ version: '2.12'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.15'
33
+ version: '1.16'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.15'
40
+ version: '1.16'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '12.0'
47
+ version: '12.3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '12.0'
54
+ version: '12.3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: minitest
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '5.10'
61
+ version: '5.11'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '5.10'
68
+ version: '5.11'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: webmock
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: '3.3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: '3.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry-byebug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '3.4'
89
+ version: '3.6'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '3.4'
96
+ version: '3.6'
97
97
  description: This is inspired by the dhl-intraship gem that is a little bit outdated
98
98
  and doesn't support the new DHL API. If you need DHL Express Services this is not
99
99
  for you.
@@ -122,7 +122,9 @@ files:
122
122
  - lib/dhl/bcs/v2/buildable.rb
123
123
  - lib/dhl/bcs/v2/client.rb
124
124
  - lib/dhl/bcs/v2/communication.rb
125
+ - lib/dhl/bcs/v2/export_document.rb
125
126
  - lib/dhl/bcs/v2/location.rb
127
+ - lib/dhl/bcs/v2/locator.rb
126
128
  - lib/dhl/bcs/v2/packstation.rb
127
129
  - lib/dhl/bcs/v2/parcel_shop.rb
128
130
  - lib/dhl/bcs/v2/postfiliale.rb
@@ -151,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
153
  version: '0'
152
154
  requirements: []
153
155
  rubyforge_project:
154
- rubygems_version: 2.6.11
156
+ rubygems_version: 2.7.3
155
157
  signing_key:
156
158
  specification_version: 4
157
159
  summary: Client for DHL Business-Customer-Shipping SOAP API 2.0