karrio-fedex 2025.5rc1__py3-none-any.whl
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.
- karrio/mappers/fedex/__init__.py +3 -0
- karrio/mappers/fedex/mapper.py +89 -0
- karrio/mappers/fedex/proxy.py +144 -0
- karrio/mappers/fedex/settings.py +24 -0
- karrio/plugins/fedex/__init__.py +23 -0
- karrio/providers/fedex/__init__.py +24 -0
- karrio/providers/fedex/document.py +88 -0
- karrio/providers/fedex/error.py +66 -0
- karrio/providers/fedex/pickup/__init__.py +9 -0
- karrio/providers/fedex/pickup/cancel.py +79 -0
- karrio/providers/fedex/pickup/create.py +148 -0
- karrio/providers/fedex/pickup/update.py +162 -0
- karrio/providers/fedex/rate.py +357 -0
- karrio/providers/fedex/shipment/__init__.py +9 -0
- karrio/providers/fedex/shipment/cancel.py +46 -0
- karrio/providers/fedex/shipment/create.py +748 -0
- karrio/providers/fedex/tracking.py +154 -0
- karrio/providers/fedex/units.py +501 -0
- karrio/providers/fedex/utils.py +199 -0
- karrio/schemas/fedex/__init__.py +0 -0
- karrio/schemas/fedex/cancel_pickup_request.py +31 -0
- karrio/schemas/fedex/cancel_pickup_response.py +24 -0
- karrio/schemas/fedex/cancel_request.py +17 -0
- karrio/schemas/fedex/cancel_response.py +25 -0
- karrio/schemas/fedex/error_response.py +16 -0
- karrio/schemas/fedex/paperless_request.py +30 -0
- karrio/schemas/fedex/paperless_response.py +21 -0
- karrio/schemas/fedex/pickup_request.py +106 -0
- karrio/schemas/fedex/pickup_response.py +25 -0
- karrio/schemas/fedex/rating_request.py +478 -0
- karrio/schemas/fedex/rating_responses.py +208 -0
- karrio/schemas/fedex/shipping_request.py +731 -0
- karrio/schemas/fedex/shipping_responses.py +584 -0
- karrio/schemas/fedex/tracking_document_request.py +30 -0
- karrio/schemas/fedex/tracking_document_response.py +30 -0
- karrio/schemas/fedex/tracking_request.py +23 -0
- karrio/schemas/fedex/tracking_response.py +350 -0
- karrio_fedex-2025.5rc1.dist-info/METADATA +45 -0
- karrio_fedex-2025.5rc1.dist-info/RECORD +42 -0
- karrio_fedex-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_fedex-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_fedex-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
import karrio.schemas.fedex.tracking_document_request as fedex
|
2
|
+
import gzip
|
3
|
+
import typing
|
4
|
+
import datetime
|
5
|
+
import urllib.parse
|
6
|
+
import karrio.lib as lib
|
7
|
+
import karrio.core as core
|
8
|
+
import karrio.core.errors as errors
|
9
|
+
|
10
|
+
|
11
|
+
class Settings(core.Settings):
|
12
|
+
"""FedEx connection settings."""
|
13
|
+
|
14
|
+
api_key: str = None
|
15
|
+
secret_key: str = None
|
16
|
+
account_number: str = None
|
17
|
+
track_api_key: str = None
|
18
|
+
track_secret_key: str = None
|
19
|
+
|
20
|
+
account_country_code: str = None
|
21
|
+
metadata: dict = {}
|
22
|
+
config: dict = {}
|
23
|
+
id: str = None
|
24
|
+
|
25
|
+
@property
|
26
|
+
def carrier_name(self):
|
27
|
+
return "fedex"
|
28
|
+
|
29
|
+
@property
|
30
|
+
def server_url(self):
|
31
|
+
return (
|
32
|
+
"https://apis-sandbox.fedex.com"
|
33
|
+
if self.test_mode
|
34
|
+
else "https://apis.fedex.com"
|
35
|
+
)
|
36
|
+
|
37
|
+
@property
|
38
|
+
def tracking_url(self):
|
39
|
+
return "https://www.fedex.com/fedextrack/?trknbr={}"
|
40
|
+
|
41
|
+
@property
|
42
|
+
def connection_config(self) -> lib.units.Options:
|
43
|
+
from karrio.providers.fedex.units import ConnectionConfig
|
44
|
+
|
45
|
+
return lib.to_connection_config(
|
46
|
+
self.config or {},
|
47
|
+
option_type=ConnectionConfig,
|
48
|
+
)
|
49
|
+
|
50
|
+
@property
|
51
|
+
def default_currency(self) -> typing.Optional[str]:
|
52
|
+
return lib.units.CountryCurrency.map(self.account_country_code).value
|
53
|
+
|
54
|
+
@property
|
55
|
+
def access_token(self):
|
56
|
+
"""Retrieve the access_token using the api_key|secret_key pair
|
57
|
+
or collect it from the cache if an unexpired access_token exist.
|
58
|
+
"""
|
59
|
+
if not all([self.api_key, self.secret_key, self.account_number]):
|
60
|
+
raise Exception(
|
61
|
+
"The api_key, secret_key and account_number are required for Rate, Ship and Other API requests."
|
62
|
+
)
|
63
|
+
|
64
|
+
cache_key = f"{self.carrier_name}|{self.api_key}|{self.secret_key}"
|
65
|
+
now = datetime.datetime.now() + datetime.timedelta(minutes=30)
|
66
|
+
|
67
|
+
auth = self.connection_cache.get(cache_key) or {}
|
68
|
+
token = auth.get("access_token")
|
69
|
+
expiry = lib.to_date(auth.get("expiry"), current_format="%Y-%m-%d %H:%M:%S")
|
70
|
+
|
71
|
+
if token is not None and expiry is not None and expiry > now:
|
72
|
+
return token
|
73
|
+
|
74
|
+
self.connection_cache.set(
|
75
|
+
cache_key,
|
76
|
+
lambda: login(
|
77
|
+
self,
|
78
|
+
client_id=self.api_key,
|
79
|
+
client_secret=self.secret_key,
|
80
|
+
),
|
81
|
+
)
|
82
|
+
new_auth = self.connection_cache.get(cache_key)
|
83
|
+
|
84
|
+
return new_auth["access_token"]
|
85
|
+
|
86
|
+
@property
|
87
|
+
def track_access_token(self):
|
88
|
+
"""Retrieve the access_token using the track_api_key|track_secret_key pair
|
89
|
+
or collect it from the cache if an unexpired access_token exist.
|
90
|
+
"""
|
91
|
+
if not all([self.track_api_key, self.track_secret_key]):
|
92
|
+
raise Exception(
|
93
|
+
"The track_api_key and track_secret_key are required for Track API requests."
|
94
|
+
)
|
95
|
+
|
96
|
+
cache_key = f"{self.carrier_name}|{self.track_api_key}|{self.track_secret_key}"
|
97
|
+
now = datetime.datetime.now() + datetime.timedelta(minutes=30)
|
98
|
+
|
99
|
+
auth = self.connection_cache.get(cache_key) or {}
|
100
|
+
token = auth.get("access_token")
|
101
|
+
expiry = lib.to_date(auth.get("expiry"), current_format="%Y-%m-%d %H:%M:%S")
|
102
|
+
|
103
|
+
if token is not None and expiry is not None and expiry > now:
|
104
|
+
return token
|
105
|
+
|
106
|
+
self.connection_cache.set(
|
107
|
+
cache_key,
|
108
|
+
lambda: login(
|
109
|
+
self,
|
110
|
+
client_id=self.track_api_key,
|
111
|
+
client_secret=self.track_secret_key,
|
112
|
+
),
|
113
|
+
)
|
114
|
+
new_auth = self.connection_cache.get(cache_key)
|
115
|
+
|
116
|
+
return new_auth["access_token"]
|
117
|
+
|
118
|
+
|
119
|
+
def login(settings: Settings, client_id: str = None, client_secret: str = None):
|
120
|
+
import karrio.providers.fedex.error as error
|
121
|
+
|
122
|
+
result = lib.request(
|
123
|
+
url=f"{settings.server_url}/oauth/token",
|
124
|
+
method="POST",
|
125
|
+
headers={
|
126
|
+
"content-Type": "application/x-www-form-urlencoded",
|
127
|
+
},
|
128
|
+
data=urllib.parse.urlencode(
|
129
|
+
dict(
|
130
|
+
grant_type="client_credentials",
|
131
|
+
client_id=client_id,
|
132
|
+
client_secret=client_secret,
|
133
|
+
)
|
134
|
+
),
|
135
|
+
)
|
136
|
+
|
137
|
+
response = lib.to_dict(result)
|
138
|
+
messages = error.parse_error_response(response, settings)
|
139
|
+
|
140
|
+
if any(messages):
|
141
|
+
raise errors.ParsedMessagesError(messages)
|
142
|
+
|
143
|
+
expiry = datetime.datetime.now() + datetime.timedelta(
|
144
|
+
seconds=float(response.get("expires_in", 0))
|
145
|
+
)
|
146
|
+
|
147
|
+
return {**response, "expiry": lib.fdatetime(expiry)}
|
148
|
+
|
149
|
+
|
150
|
+
def get_proof_of_delivery(tracking_number: str, settings: Settings):
|
151
|
+
import karrio.providers.fedex.error as error
|
152
|
+
|
153
|
+
request = fedex.TrackingDocumentRequestType(
|
154
|
+
trackDocumentSpecification=[
|
155
|
+
fedex.TrackDocumentSpecificationType(
|
156
|
+
trackingNumberInfo=fedex.TrackingNumberInfoType(
|
157
|
+
trackingNumber=tracking_number
|
158
|
+
)
|
159
|
+
)
|
160
|
+
],
|
161
|
+
trackDocumentDetail=fedex.TrackDocumentDetailType(
|
162
|
+
documentType="SIGNATURE_PROOF_OF_DELIVERY",
|
163
|
+
documentFormat="PNG",
|
164
|
+
),
|
165
|
+
)
|
166
|
+
response = lib.to_dict(
|
167
|
+
lib.request(
|
168
|
+
url=f"{settings.server_url}/track/v1/trackingdocuments",
|
169
|
+
data=lib.to_json(request),
|
170
|
+
method="POST",
|
171
|
+
decoder=parse_response,
|
172
|
+
on_error=lambda b: parse_response(b.read()),
|
173
|
+
)
|
174
|
+
)
|
175
|
+
|
176
|
+
messages = error.parse_error_response(response, settings)
|
177
|
+
|
178
|
+
if any(messages):
|
179
|
+
return None
|
180
|
+
|
181
|
+
return lib.failsafe(
|
182
|
+
lambda: lib.bundle_base64(response["output"]["documents"], format="PNG")
|
183
|
+
)
|
184
|
+
|
185
|
+
|
186
|
+
def parse_response(binary_string):
|
187
|
+
content = lib.failsafe(lambda: gzip.decompress(binary_string)) or binary_string
|
188
|
+
return lib.decode(content)
|
189
|
+
|
190
|
+
|
191
|
+
def state_code(address: lib.units.ComputedAddress) -> str:
|
192
|
+
if address.state_code is None:
|
193
|
+
return None
|
194
|
+
|
195
|
+
return (
|
196
|
+
"PQ"
|
197
|
+
if address.state_code.lower() == "qc" and address.country_code == "CA"
|
198
|
+
else address.state_code
|
199
|
+
)
|
File without changes
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AccountAddressOfRecordType:
|
8
|
+
streetLines: typing.Optional[typing.List[str]] = None
|
9
|
+
urbanizationCode: typing.Optional[str] = None
|
10
|
+
city: typing.Optional[str] = None
|
11
|
+
stateOrProvinceCode: typing.Optional[str] = None
|
12
|
+
postalCode: typing.Optional[int] = None
|
13
|
+
countryCode: typing.Optional[str] = None
|
14
|
+
residential: typing.Optional[bool] = None
|
15
|
+
addressClassification: typing.Optional[str] = None
|
16
|
+
|
17
|
+
|
18
|
+
@attr.s(auto_attribs=True)
|
19
|
+
class AssociatedAccountNumberType:
|
20
|
+
value: typing.Optional[str] = None
|
21
|
+
|
22
|
+
|
23
|
+
@attr.s(auto_attribs=True)
|
24
|
+
class CancelPickupRequestType:
|
25
|
+
associatedAccountNumber: typing.Optional[AssociatedAccountNumberType] = jstruct.JStruct[AssociatedAccountNumberType]
|
26
|
+
pickupConfirmationCode: typing.Optional[int] = None
|
27
|
+
remarks: typing.Optional[str] = None
|
28
|
+
carrierCode: typing.Optional[str] = None
|
29
|
+
accountAddressOfRecord: typing.Optional[AccountAddressOfRecordType] = jstruct.JStruct[AccountAddressOfRecordType]
|
30
|
+
scheduledDate: typing.Optional[str] = None
|
31
|
+
location: typing.Optional[str] = None
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AlertType:
|
8
|
+
code: typing.Optional[str] = None
|
9
|
+
alertType: typing.Optional[str] = None
|
10
|
+
message: typing.Optional[str] = None
|
11
|
+
|
12
|
+
|
13
|
+
@attr.s(auto_attribs=True)
|
14
|
+
class OutputType:
|
15
|
+
pickupConfirmationCode: typing.Optional[str] = None
|
16
|
+
cancelConfirmationMessage: typing.Optional[str] = None
|
17
|
+
alerts: typing.Optional[typing.List[AlertType]] = jstruct.JList[AlertType]
|
18
|
+
|
19
|
+
|
20
|
+
@attr.s(auto_attribs=True)
|
21
|
+
class CancelPickupResponseType:
|
22
|
+
transactionId: typing.Optional[str] = None
|
23
|
+
customerTransactionId: typing.Optional[str] = None
|
24
|
+
output: typing.Optional[OutputType] = jstruct.JStruct[OutputType]
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AccountNumberType:
|
8
|
+
value: typing.Optional[str] = None
|
9
|
+
|
10
|
+
|
11
|
+
@attr.s(auto_attribs=True)
|
12
|
+
class CancelRequestType:
|
13
|
+
accountNumber: typing.Optional[AccountNumberType] = jstruct.JStruct[AccountNumberType]
|
14
|
+
emailShipment: typing.Optional[bool] = None
|
15
|
+
senderCountryCode: typing.Optional[str] = None
|
16
|
+
deletionControl: typing.Optional[str] = None
|
17
|
+
trackingNumber: typing.Optional[str] = None
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AlertType:
|
8
|
+
code: typing.Optional[str] = None
|
9
|
+
alertType: typing.Optional[str] = None
|
10
|
+
message: typing.Optional[str] = None
|
11
|
+
|
12
|
+
|
13
|
+
@attr.s(auto_attribs=True)
|
14
|
+
class OutputType:
|
15
|
+
cancelledShipment: typing.Optional[bool] = None
|
16
|
+
cancelledHistory: typing.Optional[bool] = None
|
17
|
+
successMessage: typing.Optional[str] = None
|
18
|
+
alerts: typing.Optional[typing.List[AlertType]] = jstruct.JList[AlertType]
|
19
|
+
|
20
|
+
|
21
|
+
@attr.s(auto_attribs=True)
|
22
|
+
class CancelResponseType:
|
23
|
+
transactionId: typing.Optional[str] = None
|
24
|
+
customerTransactionId: typing.Optional[str] = None
|
25
|
+
output: typing.Optional[OutputType] = jstruct.JStruct[OutputType]
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class ErrorType:
|
8
|
+
code: typing.Optional[str] = None
|
9
|
+
message: typing.Optional[str] = None
|
10
|
+
|
11
|
+
|
12
|
+
@attr.s(auto_attribs=True)
|
13
|
+
class ErrorResponseType:
|
14
|
+
transactionId: typing.Optional[str] = None
|
15
|
+
customerTransactionId: typing.Optional[str] = None
|
16
|
+
errors: typing.Optional[typing.List[ErrorType]] = jstruct.JList[ErrorType]
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class MetaType:
|
8
|
+
shipDocumentType: typing.Optional[str] = None
|
9
|
+
formCode: typing.Optional[str] = None
|
10
|
+
trackingNumber: typing.Optional[str] = None
|
11
|
+
shipmentDate: typing.Optional[str] = None
|
12
|
+
originLocationCode: typing.Optional[str] = None
|
13
|
+
originCountryCode: typing.Optional[str] = None
|
14
|
+
destinationLocationCode: typing.Optional[str] = None
|
15
|
+
destinationCountryCode: typing.Optional[str] = None
|
16
|
+
|
17
|
+
|
18
|
+
@attr.s(auto_attribs=True)
|
19
|
+
class DocumentType:
|
20
|
+
workflowName: typing.Optional[str] = None
|
21
|
+
carrierCode: typing.Optional[str] = None
|
22
|
+
name: typing.Optional[str] = None
|
23
|
+
contentType: typing.Optional[str] = None
|
24
|
+
meta: typing.Optional[MetaType] = jstruct.JStruct[MetaType]
|
25
|
+
|
26
|
+
|
27
|
+
@attr.s(auto_attribs=True)
|
28
|
+
class PaperlessRequestType:
|
29
|
+
document: typing.Optional[DocumentType] = jstruct.JStruct[DocumentType]
|
30
|
+
attachment: typing.Optional[str] = None
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class MetaType:
|
8
|
+
documentType: typing.Optional[str] = None
|
9
|
+
docId: typing.Optional[str] = None
|
10
|
+
folderId: typing.Optional[typing.List[str]] = None
|
11
|
+
|
12
|
+
|
13
|
+
@attr.s(auto_attribs=True)
|
14
|
+
class OutputType:
|
15
|
+
meta: typing.Optional[MetaType] = jstruct.JStruct[MetaType]
|
16
|
+
|
17
|
+
|
18
|
+
@attr.s(auto_attribs=True)
|
19
|
+
class PaperlessResponseType:
|
20
|
+
output: typing.Optional[OutputType] = jstruct.JStruct[OutputType]
|
21
|
+
customerTransactionId: typing.Optional[str] = None
|
@@ -0,0 +1,106 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AccountAddressOfRecordType:
|
8
|
+
streetLines: typing.Optional[typing.List[str]] = None
|
9
|
+
city: typing.Optional[str] = None
|
10
|
+
stateOrProvinceCode: typing.Optional[str] = None
|
11
|
+
postalCode: typing.Optional[int] = None
|
12
|
+
countryCode: typing.Optional[str] = None
|
13
|
+
residential: typing.Optional[bool] = None
|
14
|
+
addressClassification: typing.Optional[str] = None
|
15
|
+
urbanizationCode: typing.Optional[str] = None
|
16
|
+
|
17
|
+
|
18
|
+
@attr.s(auto_attribs=True)
|
19
|
+
class AccountNumberType:
|
20
|
+
value: typing.Optional[str] = None
|
21
|
+
|
22
|
+
|
23
|
+
@attr.s(auto_attribs=True)
|
24
|
+
class DimensionsType:
|
25
|
+
length: typing.Optional[int] = None
|
26
|
+
width: typing.Optional[int] = None
|
27
|
+
height: typing.Optional[int] = None
|
28
|
+
units: typing.Optional[str] = None
|
29
|
+
|
30
|
+
|
31
|
+
@attr.s(auto_attribs=True)
|
32
|
+
class ExpressFreightDetailType:
|
33
|
+
truckType: typing.Optional[str] = None
|
34
|
+
service: typing.Optional[str] = None
|
35
|
+
trailerLength: typing.Optional[str] = None
|
36
|
+
bookingNumber: typing.Optional[str] = None
|
37
|
+
dimensions: typing.Optional[DimensionsType] = jstruct.JStruct[DimensionsType]
|
38
|
+
|
39
|
+
|
40
|
+
@attr.s(auto_attribs=True)
|
41
|
+
class ContactType:
|
42
|
+
companyName: typing.Optional[str] = None
|
43
|
+
personName: typing.Optional[str] = None
|
44
|
+
phoneNumber: typing.Optional[str] = None
|
45
|
+
phoneExtension: typing.Optional[str] = None
|
46
|
+
|
47
|
+
|
48
|
+
@attr.s(auto_attribs=True)
|
49
|
+
class PickupLocationType:
|
50
|
+
contact: typing.Optional[ContactType] = jstruct.JStruct[ContactType]
|
51
|
+
address: typing.Optional[AccountAddressOfRecordType] = jstruct.JStruct[AccountAddressOfRecordType]
|
52
|
+
accountNumber: typing.Optional[AccountNumberType] = jstruct.JStruct[AccountNumberType]
|
53
|
+
deliveryInstructions: typing.Optional[str] = None
|
54
|
+
|
55
|
+
|
56
|
+
@attr.s(auto_attribs=True)
|
57
|
+
class OriginDetailType:
|
58
|
+
pickupAddressType: typing.Optional[str] = None
|
59
|
+
pickupLocation: typing.Optional[PickupLocationType] = jstruct.JStruct[PickupLocationType]
|
60
|
+
readyDateTimestamp: typing.Optional[str] = None
|
61
|
+
customerCloseTime: typing.Optional[str] = None
|
62
|
+
pickupDateType: typing.Optional[str] = None
|
63
|
+
packageLocation: typing.Optional[str] = None
|
64
|
+
buildingPart: typing.Optional[str] = None
|
65
|
+
buildingPartDescription: typing.Optional[int] = None
|
66
|
+
earlyPickup: typing.Optional[bool] = None
|
67
|
+
suppliesRequested: typing.Optional[str] = None
|
68
|
+
geographicalPostalCode: typing.Optional[str] = None
|
69
|
+
|
70
|
+
|
71
|
+
@attr.s(auto_attribs=True)
|
72
|
+
class EmailDetailType:
|
73
|
+
address: typing.Optional[str] = None
|
74
|
+
locale: typing.Optional[str] = None
|
75
|
+
|
76
|
+
|
77
|
+
@attr.s(auto_attribs=True)
|
78
|
+
class PickupNotificationDetailType:
|
79
|
+
emailDetails: typing.Optional[typing.List[EmailDetailType]] = jstruct.JList[EmailDetailType]
|
80
|
+
format: typing.Optional[str] = None
|
81
|
+
userMessage: typing.Optional[str] = None
|
82
|
+
|
83
|
+
|
84
|
+
@attr.s(auto_attribs=True)
|
85
|
+
class TotalWeightType:
|
86
|
+
units: typing.Optional[str] = None
|
87
|
+
value: typing.Optional[int] = None
|
88
|
+
|
89
|
+
|
90
|
+
@attr.s(auto_attribs=True)
|
91
|
+
class PickupRequestType:
|
92
|
+
associatedAccountNumber: typing.Optional[AccountNumberType] = jstruct.JStruct[AccountNumberType]
|
93
|
+
originDetail: typing.Optional[OriginDetailType] = jstruct.JStruct[OriginDetailType]
|
94
|
+
associatedAccountNumberType: typing.Optional[str] = None
|
95
|
+
totalWeight: typing.Optional[TotalWeightType] = jstruct.JStruct[TotalWeightType]
|
96
|
+
packageCount: typing.Optional[int] = None
|
97
|
+
carrierCode: typing.Optional[str] = None
|
98
|
+
accountAddressOfRecord: typing.Optional[AccountAddressOfRecordType] = jstruct.JStruct[AccountAddressOfRecordType]
|
99
|
+
remarks: typing.Optional[str] = None
|
100
|
+
countryRelationships: typing.Optional[str] = None
|
101
|
+
pickupType: typing.Optional[str] = None
|
102
|
+
trackingNumber: typing.Optional[str] = None
|
103
|
+
commodityDescription: typing.Optional[str] = None
|
104
|
+
expressFreightDetail: typing.Optional[ExpressFreightDetailType] = jstruct.JStruct[ExpressFreightDetailType]
|
105
|
+
oversizePackageCount: typing.Optional[int] = None
|
106
|
+
pickupNotificationDetail: typing.Optional[PickupNotificationDetailType] = jstruct.JStruct[PickupNotificationDetailType]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import attr
|
2
|
+
import jstruct
|
3
|
+
import typing
|
4
|
+
|
5
|
+
|
6
|
+
@attr.s(auto_attribs=True)
|
7
|
+
class AlertType:
|
8
|
+
code: typing.Optional[str] = None
|
9
|
+
alertType: typing.Optional[str] = None
|
10
|
+
message: typing.Optional[str] = None
|
11
|
+
|
12
|
+
|
13
|
+
@attr.s(auto_attribs=True)
|
14
|
+
class OutputType:
|
15
|
+
pickupConfirmationCode: typing.Optional[int] = None
|
16
|
+
message: typing.Optional[str] = None
|
17
|
+
location: typing.Optional[str] = None
|
18
|
+
alerts: typing.Optional[typing.List[AlertType]] = jstruct.JList[AlertType]
|
19
|
+
|
20
|
+
|
21
|
+
@attr.s(auto_attribs=True)
|
22
|
+
class PickupResponseType:
|
23
|
+
transactionId: typing.Optional[str] = None
|
24
|
+
customerTransactionId: typing.Optional[str] = None
|
25
|
+
output: typing.Optional[OutputType] = jstruct.JStruct[OutputType]
|