deliveries 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/.github/workflows/main.yml +19 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +34 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +127 -0
- data/LICENSE.txt +21 -0
- data/README.md +207 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/deliveries.gemspec +36 -0
- data/lib/deliveries/address.rb +71 -0
- data/lib/deliveries/checkpoint.rb +12 -0
- data/lib/deliveries/collection_point.rb +45 -0
- data/lib/deliveries/courier.rb +69 -0
- data/lib/deliveries/couriers/correos_express/address.rb +31 -0
- data/lib/deliveries/couriers/correos_express/collection_points/search/format_response.rb +82 -0
- data/lib/deliveries/couriers/correos_express/collection_points/search.rb +56 -0
- data/lib/deliveries/couriers/correos_express/labels/generate.rb +68 -0
- data/lib/deliveries/couriers/correos_express/pickups/create/defaults.rb +60 -0
- data/lib/deliveries/couriers/correos_express/pickups/create/format_params.rb +95 -0
- data/lib/deliveries/couriers/correos_express/pickups/create.rb +66 -0
- data/lib/deliveries/couriers/correos_express/pickups/cutoff_time/format_params.rb +40 -0
- data/lib/deliveries/couriers/correos_express/pickups/cutoff_time.rb +61 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/correos.test.wsdl +163 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/correos.wsdl +163 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace/format_response.rb +71 -0
- data/lib/deliveries/couriers/correos_express/pickups/trace.rb +49 -0
- data/lib/deliveries/couriers/correos_express/shipments/create/defaults.rb +80 -0
- data/lib/deliveries/couriers/correos_express/shipments/create/format_params.rb +99 -0
- data/lib/deliveries/couriers/correos_express/shipments/create.rb +101 -0
- data/lib/deliveries/couriers/correos_express/shipments/trace/format_response.rb +67 -0
- data/lib/deliveries/couriers/correos_express/shipments/trace.rb +65 -0
- data/lib/deliveries/couriers/correos_express.rb +162 -0
- data/lib/deliveries/couriers/dummy.rb +106 -0
- data/lib/deliveries/couriers/mondial_relay/address.rb +31 -0
- data/lib/deliveries/couriers/mondial_relay/collection_points/search/format_response.rb +103 -0
- data/lib/deliveries/couriers/mondial_relay/labels/generate.rb +40 -0
- data/lib/deliveries/couriers/mondial_relay/pickups/create/format_params.rb +57 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create/defaults.rb +96 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create/format_params.rb +68 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/create.rb +36 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/trace/format_response.rb +94 -0
- data/lib/deliveries/couriers/mondial_relay/shipments/trace.rb +47 -0
- data/lib/deliveries/couriers/mondial_relay/status_codes.rb +105 -0
- data/lib/deliveries/couriers/mondial_relay.rb +189 -0
- data/lib/deliveries/couriers/mondial_relay_dual/address.rb +31 -0
- data/lib/deliveries/couriers/mondial_relay_dual/pickups/create/format_params.rb +39 -0
- data/lib/deliveries/couriers/mondial_relay_dual/shipments/create/format_params.rb +101 -0
- data/lib/deliveries/couriers/mondial_relay_dual/shipments/create.rb +133 -0
- data/lib/deliveries/couriers/mondial_relay_dual.rb +105 -0
- data/lib/deliveries/couriers/spring/address.rb +23 -0
- data/lib/deliveries/couriers/spring/labels/generate.rb +33 -0
- data/lib/deliveries/couriers/spring/request.rb +43 -0
- data/lib/deliveries/couriers/spring/shipments/create/defaults.rb +73 -0
- data/lib/deliveries/couriers/spring/shipments/create/format_params.rb +77 -0
- data/lib/deliveries/couriers/spring/shipments/create.rb +45 -0
- data/lib/deliveries/couriers/spring/shipments/trace/format_response.rb +79 -0
- data/lib/deliveries/couriers/spring/shipments/trace.rb +29 -0
- data/lib/deliveries/couriers/spring.rb +84 -0
- data/lib/deliveries/couriers/ups/collection_points/search.rb +142 -0
- data/lib/deliveries/couriers/ups/json_request.rb +40 -0
- data/lib/deliveries/couriers/ups/labels/generate.rb +72 -0
- data/lib/deliveries/couriers/ups/shipments/create.rb +210 -0
- data/lib/deliveries/couriers/ups/shipments/trace.rb +79 -0
- data/lib/deliveries/couriers/ups.rb +122 -0
- data/lib/deliveries/couriers.rb +14 -0
- data/lib/deliveries/delivery.rb +20 -0
- data/lib/deliveries/errors.rb +22 -0
- data/lib/deliveries/label.rb +20 -0
- data/lib/deliveries/label_utils.rb +67 -0
- data/lib/deliveries/labels.rb +40 -0
- data/lib/deliveries/pickup.rb +15 -0
- data/lib/deliveries/shipment.rb +15 -0
- data/lib/deliveries/tracking_info.rb +29 -0
- data/lib/deliveries/version.rb +5 -0
- data/lib/deliveries.rb +63 -0
- metadata +240 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Deliveries
|
4
|
+
module Couriers
|
5
|
+
module CorreosExpress
|
6
|
+
module Shipments
|
7
|
+
class Create
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
attr_accessor :sender, :receiver, :collection_point, :parcels,
|
11
|
+
:reference_code, :shipment_date, :remarks
|
12
|
+
|
13
|
+
def initialize(sender:, receiver:, collection_point:, parcels:,
|
14
|
+
reference_code:, shipment_date:, remarks:)
|
15
|
+
self.sender = sender
|
16
|
+
self.receiver = receiver
|
17
|
+
self.collection_point = collection_point
|
18
|
+
self.parcels = parcels
|
19
|
+
self.reference_code = reference_code
|
20
|
+
self.shipment_date = shipment_date
|
21
|
+
self.remarks = remarks
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute
|
25
|
+
auth = {
|
26
|
+
username: CorreosExpress.config(:username),
|
27
|
+
password: CorreosExpress.config(:password)
|
28
|
+
}
|
29
|
+
|
30
|
+
params = FormatParams.new(
|
31
|
+
sender: sender.courierize(:correos_express),
|
32
|
+
receiver: receiver.courierize(:correos_express),
|
33
|
+
collection_point: collection_point,
|
34
|
+
parcels: parcels,
|
35
|
+
reference_code: reference_code,
|
36
|
+
shipment_date: shipment_date,
|
37
|
+
remarks: remarks
|
38
|
+
).execute
|
39
|
+
|
40
|
+
response = self.class.post(
|
41
|
+
api_endpoint,
|
42
|
+
basic_auth: auth,
|
43
|
+
body: params,
|
44
|
+
headers: headers,
|
45
|
+
debug_output: Deliveries.debug ? Deliveries.logger : nil
|
46
|
+
)
|
47
|
+
raise Deliveries::ClientError unless response.success?
|
48
|
+
|
49
|
+
parsed_response = JSON.parse(response.body, symbolize_names: true)
|
50
|
+
if parsed_response[:codigoRetorno].zero? && parsed_response.key?(:datosResultado)
|
51
|
+
tracking_code = parsed_response[:datosResultado]
|
52
|
+
decoded_label = decode_label(parsed_response.dig(:etiqueta, 0, :etiqueta1))
|
53
|
+
label = Label.new(raw: decoded_label) if decoded_label
|
54
|
+
|
55
|
+
Deliveries::Shipment.new(
|
56
|
+
courier_id: 'correos_express',
|
57
|
+
sender: sender,
|
58
|
+
receiver: receiver,
|
59
|
+
parcels: parcels,
|
60
|
+
reference_code: reference_code,
|
61
|
+
tracking_code: tracking_code,
|
62
|
+
shipment_date: shipment_date,
|
63
|
+
label: label
|
64
|
+
)
|
65
|
+
else
|
66
|
+
raise Deliveries::APIError.new(
|
67
|
+
parsed_response[:mensajeRetorno],
|
68
|
+
parsed_response[:codigoRetorno]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def api_endpoint
|
76
|
+
if CorreosExpress.live?
|
77
|
+
CorreosExpress::SHIPMENTS_ENDPOINT_LIVE
|
78
|
+
else
|
79
|
+
CorreosExpress::SHIPMENTS_ENDPOINT_TEST
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def headers
|
84
|
+
{ 'Content-Type' => "application/json; charset='UTF-8'" }
|
85
|
+
end
|
86
|
+
|
87
|
+
def decode_label(encoded_label)
|
88
|
+
return nil if encoded_label.blank?
|
89
|
+
|
90
|
+
decoded_label = Base64.decode64(Base64.decode64(encoded_label)).force_encoding('binary')
|
91
|
+
|
92
|
+
# Check pdf file signature
|
93
|
+
return nil unless decoded_label[0..4].unpack1('H*').hex == 0x255044462d
|
94
|
+
|
95
|
+
decoded_label
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'active_support/time'
|
2
|
+
|
3
|
+
module Deliveries
|
4
|
+
module Couriers
|
5
|
+
module CorreosExpress
|
6
|
+
module Shipments
|
7
|
+
class Trace
|
8
|
+
class FormatResponse
|
9
|
+
attr_accessor :response
|
10
|
+
|
11
|
+
def initialize(response:)
|
12
|
+
self.response = response
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
tracking_info_params = {}
|
17
|
+
tracking_info_params[:courier_id] = 'correos_express'
|
18
|
+
tracking_info_params[:tracking_code] = response['NumEnvio']
|
19
|
+
tracking_info_params[:status] = status(response['DescEstado'])
|
20
|
+
tracking_info_params[:checkpoints] = formatted_checkpoints(response['EstadoEnvios'])
|
21
|
+
|
22
|
+
tracking_info_params
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def formatted_checkpoints(shipment_statuses)
|
28
|
+
checkpoints = []
|
29
|
+
if shipment_statuses.is_a?(Array)
|
30
|
+
shipment_statuses.each do |shipment_status|
|
31
|
+
checkpoints << formatted_checkpoint(shipment_status)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
checkpoints << formatted_checkpoint(shipment_statuses)
|
35
|
+
end
|
36
|
+
|
37
|
+
checkpoints
|
38
|
+
end
|
39
|
+
|
40
|
+
def formatted_checkpoint(shipment_status)
|
41
|
+
Deliveries::Checkpoint.new(
|
42
|
+
status: status(shipment_status['DescEstado']),
|
43
|
+
location: nil,
|
44
|
+
tracked_at: Time.zone.strptime("#{shipment_status['FechaEstado']} #{shipment_status['HoraEstado']}",
|
45
|
+
'%d%m%Y %H%M%S'),
|
46
|
+
description: shipment_status['DescEstado']
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def status(code)
|
51
|
+
case code
|
52
|
+
when 'SIN RECEPCION'
|
53
|
+
:registered
|
54
|
+
when 'EN ARRASTRE', 'DELEGACION DESTINO', 'EN REPARTO', 'TRAMO ORIGEN'
|
55
|
+
:in_transit
|
56
|
+
when 'ENTREGADO'
|
57
|
+
:delivered
|
58
|
+
else
|
59
|
+
:unknown_status
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'active_support/core_ext/hash/conversions'
|
3
|
+
|
4
|
+
module Deliveries
|
5
|
+
module Couriers
|
6
|
+
module CorreosExpress
|
7
|
+
module Shipments
|
8
|
+
class Trace
|
9
|
+
include HTTParty
|
10
|
+
|
11
|
+
attr_accessor :tracking_code
|
12
|
+
|
13
|
+
def initialize(tracking_code:)
|
14
|
+
self.tracking_code = tracking_code
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute
|
18
|
+
auth = {
|
19
|
+
username: CorreosExpress.config(:username),
|
20
|
+
password: CorreosExpress.config(:password)
|
21
|
+
}
|
22
|
+
solicitante = CorreosExpress.config(:client_code)
|
23
|
+
|
24
|
+
xml = "<?xml version='1.0'?>
|
25
|
+
<SeguimientoEnviosRequest xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
26
|
+
xsi:noNamespaceSchemaLocation='SeguimientoEnviosRequest.xsd'>
|
27
|
+
<Solicitante>#{solicitante}</Solicitante>
|
28
|
+
<Dato>#{tracking_code}</Dato>
|
29
|
+
</SeguimientoEnviosRequest>"
|
30
|
+
|
31
|
+
response = self.class.post(
|
32
|
+
api_endpoint,
|
33
|
+
basic_auth: auth,
|
34
|
+
body: xml,
|
35
|
+
headers: { 'Content-Type' => 'application/xml' },
|
36
|
+
debug_output: Deliveries.debug ? Deliveries.logger : nil
|
37
|
+
)
|
38
|
+
|
39
|
+
raise Deliveries::ClientError unless response.success?
|
40
|
+
|
41
|
+
result = Hash.from_xml response.force_encoding(Encoding::ISO_8859_1).encode(Encoding::UTF_8)
|
42
|
+
if result['SeguimientoEnviosResponse']['Error'] == '0'
|
43
|
+
result['SeguimientoEnviosResponse']
|
44
|
+
else
|
45
|
+
raise Deliveries::APIError.new(
|
46
|
+
result['SeguimientoEnviosResponse']['MensajeError'],
|
47
|
+
result['SeguimientoEnviosResponse']['Error']
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def api_endpoint
|
55
|
+
if CorreosExpress.live?
|
56
|
+
CorreosExpress::TRACKING_INFO_ENDPOINT_LIVE
|
57
|
+
else
|
58
|
+
CorreosExpress::TRACKING_INFO_ENDPOINT_TEST
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require_relative 'correos_express/shipments/trace/format_response'
|
2
|
+
require_relative 'correos_express/shipments/trace'
|
3
|
+
require_relative 'correos_express/shipments/create/defaults'
|
4
|
+
require_relative 'correos_express/shipments/create/format_params'
|
5
|
+
require_relative 'correos_express/shipments/create'
|
6
|
+
require_relative 'correos_express/collection_points/search'
|
7
|
+
require_relative 'correos_express/collection_points/search/format_response'
|
8
|
+
require_relative 'correos_express/labels/generate'
|
9
|
+
require_relative 'correos_express/pickups/create/defaults'
|
10
|
+
require_relative 'correos_express/pickups/create/format_params'
|
11
|
+
require_relative 'correos_express/pickups/create'
|
12
|
+
require_relative 'correos_express/pickups/trace/format_response'
|
13
|
+
require_relative 'correos_express/pickups/trace'
|
14
|
+
require_relative 'correos_express/pickups/cutoff_time/format_params'
|
15
|
+
require_relative 'correos_express/pickups/cutoff_time'
|
16
|
+
require_relative 'correos_express/address'
|
17
|
+
|
18
|
+
module Deliveries
|
19
|
+
module Couriers
|
20
|
+
module CorreosExpress
|
21
|
+
extend Courier
|
22
|
+
|
23
|
+
Config = Struct.new(
|
24
|
+
:username,
|
25
|
+
:password,
|
26
|
+
:client_code,
|
27
|
+
:shipment_sender_code,
|
28
|
+
:pickup_receiver_code,
|
29
|
+
:countries
|
30
|
+
)
|
31
|
+
|
32
|
+
COLLECTION_POINTS_ENDPOINT_TEST = 'https://www.correosexpress.com/wspsc/apiRestOficina/v1/oficinas/listadoOficinasCoordenadas'.freeze
|
33
|
+
COLLECTION_POINTS_ENDPOINT_LIVE = 'https://www.correosexpress.com/wpsc/apiRestOficina/v1/oficinas/listadoOficinasCoordenadas'.freeze
|
34
|
+
SHIPMENTS_ENDPOINT_LIVE = 'https://www.correosexpress.com/wpsc/apiRestGrabacionEnvio/json/grabacionEnvio'.freeze
|
35
|
+
SHIPMENTS_ENDPOINT_TEST = 'https://test.correosexpress.com/wspsc/apiRestGrabacionEnvio/json/grabacionEnvio'.freeze
|
36
|
+
TRACKING_INFO_ENDPOINT_LIVE = 'https://www.correosexpress.com/wpsc/apiRestSeguimientoEnvios/rest/seguimientoEnvios'.freeze
|
37
|
+
TRACKING_INFO_ENDPOINT_TEST = 'https://test.correosexpress.com/wspsc/apiRestSeguimientoEnvios/rest/seguimientoEnvios'.freeze
|
38
|
+
LABELS_ENDPOINT_LIVE = 'https://www.cexpr.es/wspsc/apiRestEtiquetaTransporte/json/etiquetaTransporte'.freeze
|
39
|
+
LABELS_ENDPOINT_TEST = 'https://www.test.cexpr.es/wsps/apiRestEtiquetaTransporte/json/etiquetaTransporte'.freeze
|
40
|
+
PICKUPS_ENDPOINT_LIVE = 'https://www.correosexpress.com/wpsc/apiRestGrabacionRecogida/json/grabarRecogida'.freeze
|
41
|
+
PICKUPS_ENDPOINT_TEST = 'https://test.correosexpress.com/wpsn/apiRestGrabacionRecogida/json/grabarRecogida'.freeze
|
42
|
+
CUTOFF_TIME_ENDPOINT_LIVE = 'https://www.correosexpress.com/wpsc/apiRestGrabacionRecogida/json/horaCorte'.freeze
|
43
|
+
|
44
|
+
module_function
|
45
|
+
|
46
|
+
def get_collection_points(postcode:, **)
|
47
|
+
raise Deliveries::APIError, 'Postcode cannot be null' if postcode.blank?
|
48
|
+
|
49
|
+
collection_points = []
|
50
|
+
|
51
|
+
points = CollectionPoints::Search.new(postcode: postcode).execute
|
52
|
+
points.each do |point|
|
53
|
+
collection_point_params = CollectionPoints::Search::FormatResponse.new(response: point).execute
|
54
|
+
collection_points << Deliveries::CollectionPoint.new(collection_point_params)
|
55
|
+
end
|
56
|
+
|
57
|
+
collection_points
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_collection_point(global_point_id:)
|
61
|
+
global_point = Deliveries::CollectionPoint.parse_global_point_id(global_point_id: global_point_id)
|
62
|
+
|
63
|
+
collection_points = get_collection_points(postcode: global_point.postcode)
|
64
|
+
collection_point = collection_points.select { |col| col.point_id == global_point.point_id }.first
|
65
|
+
|
66
|
+
if collection_point.blank?
|
67
|
+
raise Deliveries::APIError.new(
|
68
|
+
"Collection Point not found - #{global_point.point_id}",
|
69
|
+
1
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
collection_point
|
74
|
+
end
|
75
|
+
|
76
|
+
def shipment_info(tracking_code:, **)
|
77
|
+
response = Shipments::Trace.new(
|
78
|
+
tracking_code: tracking_code
|
79
|
+
).execute
|
80
|
+
|
81
|
+
tracking_info_params = Shipments::Trace::FormatResponse.new(response: response).execute
|
82
|
+
Deliveries::TrackingInfo.new(tracking_info_params)
|
83
|
+
end
|
84
|
+
|
85
|
+
def pickup_info(tracking_code:, **)
|
86
|
+
response = Pickups::Trace.new(
|
87
|
+
tracking_code: tracking_code
|
88
|
+
).execute
|
89
|
+
|
90
|
+
tracking_info_params = Pickups::Trace::FormatResponse.new(response: response).execute
|
91
|
+
|
92
|
+
Deliveries::TrackingInfo.new(tracking_info_params)
|
93
|
+
end
|
94
|
+
|
95
|
+
def get_label(tracking_code:, **)
|
96
|
+
pdf = Labels::Generate.new(
|
97
|
+
tracking_codes: tracking_code
|
98
|
+
).execute.first
|
99
|
+
|
100
|
+
Deliveries::Label.new(raw: pdf)
|
101
|
+
end
|
102
|
+
|
103
|
+
def get_labels(tracking_codes:, **)
|
104
|
+
labels = Deliveries::Labels.new
|
105
|
+
|
106
|
+
Labels::Generate.new(
|
107
|
+
tracking_codes: tracking_codes
|
108
|
+
).execute.each do |pdf|
|
109
|
+
labels << pdf
|
110
|
+
end
|
111
|
+
|
112
|
+
labels
|
113
|
+
end
|
114
|
+
|
115
|
+
def create_shipment(sender:, receiver:, parcels:, reference_code:, collection_point: nil, shipment_date: nil, remarks: nil, **)
|
116
|
+
Shipments::Create.new(
|
117
|
+
sender: sender,
|
118
|
+
receiver: receiver,
|
119
|
+
collection_point: collection_point,
|
120
|
+
shipment_date: shipment_date,
|
121
|
+
parcels: parcels,
|
122
|
+
reference_code: reference_code,
|
123
|
+
remarks: remarks
|
124
|
+
).execute
|
125
|
+
end
|
126
|
+
|
127
|
+
def create_pickup(sender:, receiver:, parcels:, reference_code:,
|
128
|
+
pickup_date: nil, remarks: nil, **)
|
129
|
+
time_interval = nil
|
130
|
+
begin
|
131
|
+
params = Pickups::Create::FormatParams.new(
|
132
|
+
sender: sender.courierize(:correos_express),
|
133
|
+
receiver: receiver.courierize(:correos_express),
|
134
|
+
parcels: parcels,
|
135
|
+
reference_code: reference_code,
|
136
|
+
pickup_date: pickup_date,
|
137
|
+
remarks: remarks,
|
138
|
+
time_interval: time_interval
|
139
|
+
).execute
|
140
|
+
|
141
|
+
pickup_number = Pickups::Create.new(params: params).execute
|
142
|
+
rescue InvalidTimeIntervalError => e
|
143
|
+
raise e if time_interval
|
144
|
+
raise e unless (cutoff_time = e.message[/\b(\d+):\d{2}\z/, 1])
|
145
|
+
|
146
|
+
time_interval = 9..cutoff_time.to_i
|
147
|
+
retry
|
148
|
+
end
|
149
|
+
|
150
|
+
Deliveries::Pickup.new(
|
151
|
+
courier_id: 'correos_express',
|
152
|
+
sender: sender,
|
153
|
+
receiver: receiver,
|
154
|
+
parcels: parcels,
|
155
|
+
reference_code: reference_code,
|
156
|
+
tracking_code: pickup_number,
|
157
|
+
pickup_date: pickup_date
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module Dummy
|
4
|
+
extend Courier
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def get_collection_point(global_point_id:)
|
9
|
+
point = CollectionPoint.parse_global_point_id global_point_id: global_point_id
|
10
|
+
CollectionPoint.new name: 'Dummy',
|
11
|
+
email: 'dummy@dummy.com',
|
12
|
+
phone: '555 555 555',
|
13
|
+
country: point.country.to_sym,
|
14
|
+
state: 'Bizkaia',
|
15
|
+
city: 'Erandio',
|
16
|
+
street: 'Axpe',
|
17
|
+
postcode: point.postcode,
|
18
|
+
courier_id: 'dummy',
|
19
|
+
point_id: point.point_id,
|
20
|
+
latitude: 43.312132,
|
21
|
+
longitude: -2.979586,
|
22
|
+
timetable: {
|
23
|
+
0 => [],
|
24
|
+
1 => [OpenStruct.new(open: '8:00', close: '14:00'),
|
25
|
+
OpenStruct.new(open: '16:00', close: '20:00')],
|
26
|
+
2 => [OpenStruct.new(open: '8:00', close: '14:00'),
|
27
|
+
OpenStruct.new(open: '16:00', close: '20:00')],
|
28
|
+
3 => [OpenStruct.new(open: '8:00', close: '14:00'),
|
29
|
+
OpenStruct.new(open: '16:00', close: '20:00')],
|
30
|
+
4 => [OpenStruct.new(open: '8:00', close: '14:00'),
|
31
|
+
OpenStruct.new(open: '16:00', close: '20:00')],
|
32
|
+
5 => [OpenStruct.new(open: '8:00', close: '15:00')],
|
33
|
+
6 => []
|
34
|
+
},
|
35
|
+
url_map: nil,
|
36
|
+
url_photo: nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_collection_points(country:, postcode:)
|
40
|
+
[
|
41
|
+
get_collection_point(global_point_id: "dummy~#{country}~#{postcode}~1"),
|
42
|
+
get_collection_point(global_point_id: "dummy~#{country}~#{postcode}~2")
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
def shipment_info(tracking_code:, **)
|
47
|
+
TrackingInfo.new courier_id: 'dummy',
|
48
|
+
tracking_code: tracking_code,
|
49
|
+
status: :in_transit,
|
50
|
+
checkpoints: [
|
51
|
+
Checkpoint.new(status: :registered, location: 'Source city', tracked_at: 1.week.ago,
|
52
|
+
description: 'Parcel taken'),
|
53
|
+
Checkpoint.new(status: :in_transit, location: 'Halfway city', tracked_at: 1.day.ago,
|
54
|
+
description: 'There is some delay')
|
55
|
+
],
|
56
|
+
url: 'https://google.com'
|
57
|
+
end
|
58
|
+
|
59
|
+
def pickup_info(tracking_code:, **)
|
60
|
+
TrackingInfo.new courier_id: 'dummy',
|
61
|
+
tracking_code: tracking_code,
|
62
|
+
status: :in_transit,
|
63
|
+
checkpoints: [
|
64
|
+
Checkpoint.new(status: :registered, location: 'Source city', tracked_at: 1.week.ago,
|
65
|
+
description: 'Parcel taken'),
|
66
|
+
Checkpoint.new(status: :in_transit, location: 'Halfway city', tracked_at: 1.day.ago,
|
67
|
+
description: 'There is some delay')
|
68
|
+
],
|
69
|
+
url: 'https://google.com'
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_shipment(sender:, receiver:, parcels:, reference_code:, shipment_date: nil, **)
|
73
|
+
Shipment.new courier_id: 'dummy',
|
74
|
+
sender: sender,
|
75
|
+
receiver: receiver,
|
76
|
+
parcels: parcels,
|
77
|
+
reference_code: reference_code,
|
78
|
+
tracking_code: reference_code,
|
79
|
+
shipment_date: shipment_date
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_pickup(sender:, receiver:, parcels:, reference_code:, pickup_date: nil, **)
|
83
|
+
Pickup.new courier_id: 'dummy',
|
84
|
+
sender: sender,
|
85
|
+
receiver: receiver,
|
86
|
+
parcels: parcels,
|
87
|
+
reference_code: reference_code,
|
88
|
+
tracking_code: reference_code,
|
89
|
+
pickup_date: pickup_date
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_label(**)
|
93
|
+
pdf = <<~PDF
|
94
|
+
%PDF-1.0
|
95
|
+
1 0 obj<</Pages 2 0 R>>endobj 2 0 obj<</Kids[3 0 R]/Count 1>>endobj 3 0 obj<</MediaBox[0 0 3 3]>>endobj
|
96
|
+
trailer<</Root 1 0 R>>
|
97
|
+
PDF
|
98
|
+
Deliveries::Label.new(raw: pdf)
|
99
|
+
end
|
100
|
+
|
101
|
+
def get_labels(tracking_codes:, language: nil)
|
102
|
+
get_label tracking_code: tracking_codes, language: language
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module MondialRelay
|
4
|
+
class Address < Deliveries::Address
|
5
|
+
def name
|
6
|
+
I18n.transliterate(@name.to_s).gsub(%r{[^0-9A-Z_\-'., /]}i, '').upcase.truncate(32, omission: '')
|
7
|
+
end
|
8
|
+
|
9
|
+
def street
|
10
|
+
I18n.transliterate(@street.to_s).gsub(%r{[^0-9A-Z_\-'., /]}i, '').upcase.truncate(32, omission: '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def city
|
14
|
+
I18n.transliterate(@city.to_s).gsub(/[^A-Z_\-' ]/i, '').upcase.truncate(25, omission: '')
|
15
|
+
end
|
16
|
+
|
17
|
+
def country
|
18
|
+
@country.to_s.upcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def phone
|
22
|
+
format_international_phone
|
23
|
+
end
|
24
|
+
|
25
|
+
def email
|
26
|
+
format_email
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# :stat=>"0",
|
2
|
+
# :num=>"070912",
|
3
|
+
# :lg_adr1=>"VENANDCOM ",
|
4
|
+
# :lg_adr2=>nil,
|
5
|
+
# :lg_adr3=>"CL LANGILERIA 126 ",
|
6
|
+
# :lg_adr4=>nil,
|
7
|
+
# :cp=>"48940",
|
8
|
+
# :ville=>"LEIOA ",
|
9
|
+
# :pays=>"ES",
|
10
|
+
# :localisation1=>"ENTRE METRO LAMIACO Y ROMO ",
|
11
|
+
# :localisation2=>nil,
|
12
|
+
# :horaires_lundi=>{:string=>["1000", "1330", "1700", "2000"]},
|
13
|
+
# :horaires_mardi=>{:string=>["1000", "1330", "1700", "2000"]},
|
14
|
+
# :horaires_mercredi=>{:string=>["1000", "1330", "1700", "2000"]},
|
15
|
+
# :horaires_jeudi=>{:string=>["1000", "1330", "1700", "2000"]},
|
16
|
+
# :horaires_vendredi=>{:string=>["1000", "1330", "1700", "2000"]},
|
17
|
+
# :horaires_samedi=>{:string=>["1000", "1330", "0000", "0000"]},
|
18
|
+
# :horaires_dimanche=>{:string=>["0000", "0000", "0000", "0000"]},
|
19
|
+
# :information=>nil,
|
20
|
+
# :url_photo=>"https://ww2.mondialrelay.com/public/permanent/photo_relais.aspx?ens=CC______41&num=070912&pays=ES&crc=17576B6AE31EA66C7C66463BCDD955A4",
|
21
|
+
# :url_plan=>"https://ww2.mondialrelay.com/public/permanent/plan_relais.aspx?ens=test11&num=070912&pays=ES&crc=4F83CD143A1506242F025F9C11311A3C"}
|
22
|
+
|
23
|
+
# Deliveries.courier('mondial_relay').get_collection_point(point_id: 23191, country: 'ES')
|
24
|
+
|
25
|
+
module Deliveries
|
26
|
+
module Couriers
|
27
|
+
module MondialRelay
|
28
|
+
module CollectionPoints
|
29
|
+
class Search
|
30
|
+
class FormatResponse
|
31
|
+
WEEKDAYS_STARTING_SUNDAY = %w[
|
32
|
+
dimanche
|
33
|
+
lundi
|
34
|
+
mardi
|
35
|
+
mercredi
|
36
|
+
jeudi
|
37
|
+
vendredi
|
38
|
+
samedi
|
39
|
+
].freeze
|
40
|
+
|
41
|
+
attr_accessor :response
|
42
|
+
|
43
|
+
def initialize(response:)
|
44
|
+
self.response = response
|
45
|
+
end
|
46
|
+
|
47
|
+
def execute
|
48
|
+
point = {}
|
49
|
+
|
50
|
+
point[:courier_id] = 'mondial_relay'
|
51
|
+
point[:point_id] = response[:num]
|
52
|
+
point[:country] = response[:pays]
|
53
|
+
point[:city] = response[:ville].strip unless response[:ville].nil?
|
54
|
+
point[:postcode] = response[:cp].strip unless response[:cp].nil?
|
55
|
+
point[:url_map] = response[:url_plan]
|
56
|
+
point[:latitude] = response[:latitude].tr(',', '.').to_f
|
57
|
+
point[:longitude] = response[:longitude].tr(',', '.').to_f
|
58
|
+
point[:timetable] = formatted_timetable(response)
|
59
|
+
point[:url_photo] = response[:url_photo]
|
60
|
+
point[:name] = response[:lg_adr1].strip
|
61
|
+
point[:street] = response[:lg_adr3].strip
|
62
|
+
|
63
|
+
point
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def formatted_timetable(result)
|
69
|
+
timetable = {}
|
70
|
+
|
71
|
+
week_hours = get_week_hours_from_result(result)
|
72
|
+
week_hours.each do |i, times|
|
73
|
+
timetable[i] = []
|
74
|
+
if times[0] == '0000'
|
75
|
+
timetable[i] << nil
|
76
|
+
else
|
77
|
+
timetable[i] << formatted_slot(open: times[0], close: times[1])
|
78
|
+
timetable[i] << formatted_slot(open: times[2], close: times[3]) if times[2] != '0000'
|
79
|
+
end
|
80
|
+
timetable[i] = nil unless timetable[i].any?
|
81
|
+
end
|
82
|
+
|
83
|
+
timetable
|
84
|
+
end
|
85
|
+
|
86
|
+
def get_week_hours_from_result(result)
|
87
|
+
week_hours = {}
|
88
|
+
WEEKDAYS_STARTING_SUNDAY.each_with_index do |day, i|
|
89
|
+
week_hours[i] = result["horaires_#{day}".to_sym][:string]
|
90
|
+
end
|
91
|
+
|
92
|
+
week_hours
|
93
|
+
end
|
94
|
+
|
95
|
+
def formatted_slot(open:, close:)
|
96
|
+
OpenStruct.new(open: open.insert(2, ':'), close: close.insert(2, ':'))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Deliveries
|
2
|
+
module Couriers
|
3
|
+
module MondialRelay
|
4
|
+
module Labels
|
5
|
+
class Generate
|
6
|
+
attr_accessor :tracking_codes, :language
|
7
|
+
|
8
|
+
def initialize(tracking_codes:, language:)
|
9
|
+
self.tracking_codes = [tracking_codes].flatten.join(';')
|
10
|
+
self.language = language.to_s.upcase
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute
|
14
|
+
params = {
|
15
|
+
'Enseigne' => Deliveries::Couriers::MondialRelay.config(:mondial_relay_merchant),
|
16
|
+
'Expeditions' => tracking_codes,
|
17
|
+
'Langue' => language
|
18
|
+
}
|
19
|
+
|
20
|
+
# Calculate security parameters.
|
21
|
+
params['Security'] = Deliveries::Couriers::MondialRelay.calculate_security_param params
|
22
|
+
|
23
|
+
response = MondialRelay.api_client.call :wsi3_get_etiquettes, message: params
|
24
|
+
response_stat = response.body.dig(:wsi3_get_etiquettes_response, :wsi3_get_etiquettes_result, :stat)
|
25
|
+
if response_stat == '0'
|
26
|
+
# Get path for 10x15 format.
|
27
|
+
"http://www.mondialrelay.com#{response.body.dig(:wsi3_get_etiquettes_response,
|
28
|
+
:wsi3_get_etiquettes_result, :url_pdf_10x15)}"
|
29
|
+
else
|
30
|
+
raise Deliveries::APIError.new(
|
31
|
+
StatusCodes.message_for(response_stat.to_i),
|
32
|
+
response_stat
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|