karrio-server-proxy 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/server/proxy/__init__.py +0 -0
- karrio/server/proxy/admin.py +3 -0
- karrio/server/proxy/apps.py +5 -0
- karrio/server/proxy/migrations/__init__.py +0 -0
- karrio/server/proxy/models.py +3 -0
- karrio/server/proxy/router.py +3 -0
- karrio/server/proxy/tests/__init__.py +8 -0
- karrio/server/proxy/tests/test_pickup.py +293 -0
- karrio/server/proxy/tests/test_rating.py +100 -0
- karrio/server/proxy/tests/test_shipping.py +337 -0
- karrio/server/proxy/tests/test_tracking.py +92 -0
- karrio/server/proxy/urls.py +10 -0
- karrio/server/proxy/views/__init__.py +6 -0
- karrio/server/proxy/views/manifest.py +55 -0
- karrio/server/proxy/views/pickup.py +151 -0
- karrio/server/proxy/views/rating.py +57 -0
- karrio/server/proxy/views/shipping.py +139 -0
- karrio/server/proxy/views/tracking.py +165 -0
- karrio_server_proxy-2025.5rc1.dist-info/METADATA +27 -0
- karrio_server_proxy-2025.5rc1.dist-info/RECORD +22 -0
- karrio_server_proxy-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_server_proxy-2025.5rc1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,337 @@
|
|
1
|
+
import json
|
2
|
+
from unittest.mock import patch, ANY
|
3
|
+
from django.urls import reverse
|
4
|
+
from rest_framework import status
|
5
|
+
from karrio.core.models import ShipmentDetails, ConfirmationDetails, Message
|
6
|
+
from karrio.server.core.tests import APITestCase
|
7
|
+
|
8
|
+
|
9
|
+
class TestShipping(APITestCase):
|
10
|
+
def test_shipping_request(self):
|
11
|
+
url = reverse("karrio.server.proxy:shipping-request")
|
12
|
+
data = SHIPPING_DATA
|
13
|
+
|
14
|
+
with patch("karrio.server.core.gateway.utils.identity") as mock:
|
15
|
+
mock.return_value = RETURNED_VALUE
|
16
|
+
response = self.client.post(url, data)
|
17
|
+
response_data = json.loads(response.content)
|
18
|
+
|
19
|
+
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
20
|
+
self.assertDictEqual(response_data, SHIPPING_RESPONSE)
|
21
|
+
|
22
|
+
def test_shipping_cancel(self):
|
23
|
+
url = reverse(
|
24
|
+
"karrio.server.proxy:shipping-cancel",
|
25
|
+
kwargs=dict(carrier_name="canadapost"),
|
26
|
+
)
|
27
|
+
data = SHIPPING_CANCEL_DATA
|
28
|
+
|
29
|
+
with patch("karrio.server.core.gateway.utils.identity") as mock:
|
30
|
+
mock.return_value = RETURNED_SUCCESS_CANCEL_VALUE
|
31
|
+
response = self.client.post(f"{url}", data)
|
32
|
+
response_data = json.loads(response.content)
|
33
|
+
|
34
|
+
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
|
35
|
+
self.assertDictEqual(response_data, SHIPPING_CANCEL_SUCCESS_RESPONSE)
|
36
|
+
|
37
|
+
def test_shipping_failed_cancel(self):
|
38
|
+
url = reverse(
|
39
|
+
"karrio.server.proxy:shipping-cancel",
|
40
|
+
kwargs=dict(carrier_name="canadapost"),
|
41
|
+
)
|
42
|
+
data = SHIPPING_CANCEL_DATA
|
43
|
+
|
44
|
+
with patch("karrio.server.core.gateway.utils.identity") as mock:
|
45
|
+
mock.return_value = RETURNED_FAILED_CANCEL_VALUE
|
46
|
+
response = self.client.post(f"{url}", data)
|
47
|
+
response_data = json.loads(response.content)
|
48
|
+
|
49
|
+
self.assertEqual(response.status_code, status.HTTP_424_FAILED_DEPENDENCY)
|
50
|
+
self.assertDictEqual(response_data, SHIPPING_CANCEL_FAILED_RESPONSE)
|
51
|
+
|
52
|
+
|
53
|
+
SHIPPING_DATA = {
|
54
|
+
"selected_rate_id": "prx_a9b96e5a82f644b0921bfed3190b4d6c",
|
55
|
+
"options": {},
|
56
|
+
"recipient": {
|
57
|
+
"address_line1": "125 Church St",
|
58
|
+
"person_name": "John Doe",
|
59
|
+
"company_name": "A corp.",
|
60
|
+
"phone_number": "514 000 0000",
|
61
|
+
"city": "Moncton",
|
62
|
+
"country_code": "CA",
|
63
|
+
"postal_code": "E1C4Z8",
|
64
|
+
"residential": False,
|
65
|
+
"state_code": "NB",
|
66
|
+
"validate_location": False,
|
67
|
+
"validation": None,
|
68
|
+
},
|
69
|
+
"shipper": {
|
70
|
+
"address_line1": "5840 Oak St",
|
71
|
+
"person_name": "Jane Doe",
|
72
|
+
"company_name": "B corp.",
|
73
|
+
"phone_number": "514 000 0000",
|
74
|
+
"city": "Vancouver",
|
75
|
+
"country_code": "CA",
|
76
|
+
"postal_code": "v6m2V9",
|
77
|
+
"residential": False,
|
78
|
+
"state_code": "BC",
|
79
|
+
"validate_location": False,
|
80
|
+
"validation": None,
|
81
|
+
},
|
82
|
+
"parcels": [
|
83
|
+
{
|
84
|
+
"weight": 1,
|
85
|
+
"weight_unit": "KG",
|
86
|
+
"package_preset": "canadapost_corrugated_small_box",
|
87
|
+
}
|
88
|
+
],
|
89
|
+
"rates": [
|
90
|
+
{
|
91
|
+
"base_charge": 101.83,
|
92
|
+
"carrier_id": "canadapost",
|
93
|
+
"carrier_name": "canadapost",
|
94
|
+
"currency": "CAD",
|
95
|
+
"estimated_delivery": ANY,
|
96
|
+
"discount": -9.04,
|
97
|
+
"duties_and_taxes": 13.92,
|
98
|
+
"estimated_delivery": "2020-06-22",
|
99
|
+
"extra_charges": [
|
100
|
+
{"amount": 2.7, "currency": "CAD", "name": "Fuel surcharge"},
|
101
|
+
{"amount": -11.74, "currency": "CAD", "name": "SMB Savings"},
|
102
|
+
],
|
103
|
+
"id": "prx_a9b96e5a82f644b0921bfed3190b4d6c",
|
104
|
+
"service": "canadapost_priority",
|
105
|
+
"total_charge": 106.71,
|
106
|
+
"test_mode": True,
|
107
|
+
},
|
108
|
+
{
|
109
|
+
"base_charge": 27.36,
|
110
|
+
"carrier_id": "canadapost",
|
111
|
+
"carrier_name": "canadapost",
|
112
|
+
"currency": "CAD",
|
113
|
+
"estimated_delivery": None,
|
114
|
+
"discount": -3.06,
|
115
|
+
"duties_and_taxes": 3.65,
|
116
|
+
"estimated_delivery": "2020-07-02",
|
117
|
+
"extra_charges": [
|
118
|
+
{"amount": 0.71, "currency": "CAD", "name": "Fuel surcharge"},
|
119
|
+
{"amount": -3.77, "currency": "CAD", "name": "SMB Savings"},
|
120
|
+
],
|
121
|
+
"id": "prx_9290e4a2c8e34c8d8c73ab990b029f3d",
|
122
|
+
"service": "canadapost_regular_parcel",
|
123
|
+
"total_charge": 27.95,
|
124
|
+
"test_mode": True,
|
125
|
+
},
|
126
|
+
],
|
127
|
+
"payment": {"currency": "CAD", "paid_by": "sender"},
|
128
|
+
}
|
129
|
+
|
130
|
+
SHIPPING_CANCEL_DATA = {"shipment_identifier": "123456789012"}
|
131
|
+
|
132
|
+
RETURNED_VALUE = [
|
133
|
+
ShipmentDetails(
|
134
|
+
carrier_name="canadapost",
|
135
|
+
carrier_id="canadapost",
|
136
|
+
tracking_number="123456789012",
|
137
|
+
shipment_identifier="123456789012",
|
138
|
+
docs=dict(label="==apodifjoefr"),
|
139
|
+
),
|
140
|
+
[],
|
141
|
+
]
|
142
|
+
|
143
|
+
RETURNED_SUCCESS_CANCEL_VALUE = [
|
144
|
+
ConfirmationDetails(
|
145
|
+
carrier_name="canadapost",
|
146
|
+
carrier_id="canadapost",
|
147
|
+
success=True,
|
148
|
+
operation="Cancel Shipment",
|
149
|
+
),
|
150
|
+
[],
|
151
|
+
]
|
152
|
+
|
153
|
+
RETURNED_FAILED_CANCEL_VALUE = [
|
154
|
+
None,
|
155
|
+
[
|
156
|
+
Message(
|
157
|
+
carrier_name="canadapost",
|
158
|
+
carrier_id="canadapost",
|
159
|
+
message="Not Found",
|
160
|
+
code="404",
|
161
|
+
)
|
162
|
+
],
|
163
|
+
]
|
164
|
+
|
165
|
+
SHIPPING_RESPONSE = {
|
166
|
+
"id": ANY,
|
167
|
+
"object_type": "shipment",
|
168
|
+
"tracking_url": "/v1/proxy/tracking/canadapost/123456789012",
|
169
|
+
"shipper": {
|
170
|
+
"id": None,
|
171
|
+
"postal_code": "V6M2V9",
|
172
|
+
"city": "Vancouver",
|
173
|
+
"federal_tax_id": None,
|
174
|
+
"state_tax_id": None,
|
175
|
+
"person_name": "Jane Doe",
|
176
|
+
"company_name": "B corp.",
|
177
|
+
"country_code": "CA",
|
178
|
+
"email": None,
|
179
|
+
"phone_number": "+1 514-000-0000",
|
180
|
+
"state_code": "BC",
|
181
|
+
"street_number": None,
|
182
|
+
"residential": False,
|
183
|
+
"address_line1": "5840 Oak St",
|
184
|
+
"address_line2": "",
|
185
|
+
"validate_location": False,
|
186
|
+
"object_type": "address",
|
187
|
+
"validation": None,
|
188
|
+
},
|
189
|
+
"recipient": {
|
190
|
+
"id": None,
|
191
|
+
"postal_code": "E1C4Z8",
|
192
|
+
"city": "Moncton",
|
193
|
+
"federal_tax_id": None,
|
194
|
+
"state_tax_id": None,
|
195
|
+
"person_name": "John Doe",
|
196
|
+
"company_name": "A corp.",
|
197
|
+
"country_code": "CA",
|
198
|
+
"email": None,
|
199
|
+
"phone_number": "+1 514-000-0000",
|
200
|
+
"state_code": "NB",
|
201
|
+
"street_number": None,
|
202
|
+
"residential": False,
|
203
|
+
"address_line1": "125 Church St",
|
204
|
+
"address_line2": "",
|
205
|
+
"validate_location": False,
|
206
|
+
"object_type": "address",
|
207
|
+
"validation": None,
|
208
|
+
},
|
209
|
+
"parcels": [
|
210
|
+
{
|
211
|
+
"id": None,
|
212
|
+
"weight": 1.0,
|
213
|
+
"width": 42.0,
|
214
|
+
"height": 32.0,
|
215
|
+
"length": 32.0,
|
216
|
+
"packaging_type": None,
|
217
|
+
"package_preset": "canadapost_corrugated_small_box",
|
218
|
+
"description": None,
|
219
|
+
"content": None,
|
220
|
+
"is_document": False,
|
221
|
+
"weight_unit": "KG",
|
222
|
+
"dimension_unit": "CM",
|
223
|
+
"items": [],
|
224
|
+
"freight_class": None,
|
225
|
+
"reference_number": "123456789012",
|
226
|
+
"object_type": "parcel",
|
227
|
+
"options": {},
|
228
|
+
}
|
229
|
+
],
|
230
|
+
"services": [],
|
231
|
+
"options": {"shipment_date": ANY, "shipping_date": ANY},
|
232
|
+
"payment": {"paid_by": "sender", "currency": "CAD", "account_number": None},
|
233
|
+
"billing_address": None,
|
234
|
+
"customs": None,
|
235
|
+
"rates": [
|
236
|
+
{
|
237
|
+
"id": ANY,
|
238
|
+
"object_type": "rate",
|
239
|
+
"carrier_name": "canadapost",
|
240
|
+
"carrier_id": "canadapost",
|
241
|
+
"currency": "CAD",
|
242
|
+
"estimated_delivery": ANY,
|
243
|
+
"service": "canadapost_priority",
|
244
|
+
"total_charge": 106.71,
|
245
|
+
"transit_days": None,
|
246
|
+
"extra_charges": [
|
247
|
+
{"name": "Fuel surcharge", "amount": 2.7, "currency": "CAD"},
|
248
|
+
{"name": "SMB Savings", "amount": -11.74, "currency": "CAD"},
|
249
|
+
],
|
250
|
+
"meta": None,
|
251
|
+
"test_mode": True,
|
252
|
+
},
|
253
|
+
{
|
254
|
+
"id": ANY,
|
255
|
+
"object_type": "rate",
|
256
|
+
"carrier_name": "canadapost",
|
257
|
+
"carrier_id": "canadapost",
|
258
|
+
"currency": "CAD",
|
259
|
+
"estimated_delivery": ANY,
|
260
|
+
"service": "canadapost_regular_parcel",
|
261
|
+
"total_charge": 27.95,
|
262
|
+
"transit_days": None,
|
263
|
+
"extra_charges": [
|
264
|
+
{"name": "Fuel surcharge", "amount": 0.71, "currency": "CAD"},
|
265
|
+
{"name": "SMB Savings", "amount": -3.77, "currency": "CAD"},
|
266
|
+
],
|
267
|
+
"meta": None,
|
268
|
+
"test_mode": True,
|
269
|
+
},
|
270
|
+
],
|
271
|
+
"reference": "",
|
272
|
+
"return_address": None,
|
273
|
+
"label_type": "PDF",
|
274
|
+
"carrier_ids": [],
|
275
|
+
"tracker_id": None,
|
276
|
+
"created_at": ANY,
|
277
|
+
"metadata": {},
|
278
|
+
"messages": [],
|
279
|
+
"status": "purchased",
|
280
|
+
"carrier_name": "canadapost",
|
281
|
+
"carrier_id": "canadapost",
|
282
|
+
"tracking_number": "123456789012",
|
283
|
+
"shipment_identifier": "123456789012",
|
284
|
+
"selected_rate": {
|
285
|
+
"id": ANY,
|
286
|
+
"object_type": "rate",
|
287
|
+
"carrier_name": "canadapost",
|
288
|
+
"carrier_id": "canadapost",
|
289
|
+
"currency": "CAD",
|
290
|
+
"estimated_delivery": ANY,
|
291
|
+
"service": "canadapost_priority",
|
292
|
+
"total_charge": 106.71,
|
293
|
+
"transit_days": None,
|
294
|
+
"extra_charges": [
|
295
|
+
{"name": "Fuel surcharge", "amount": 2.7, "currency": "CAD"},
|
296
|
+
{"name": "SMB Savings", "amount": -11.74, "currency": "CAD"},
|
297
|
+
],
|
298
|
+
"meta": {
|
299
|
+
"ext": "canadapost",
|
300
|
+
"carrier": "canadapost",
|
301
|
+
"rate_provider": "canadapost",
|
302
|
+
"service_name": "CANADAPOST PRIORITY",
|
303
|
+
},
|
304
|
+
"test_mode": True,
|
305
|
+
},
|
306
|
+
"docs": {"label": "==apodifjoefr", "invoice": None},
|
307
|
+
"meta": {
|
308
|
+
"ext": "canadapost",
|
309
|
+
"carrier": "canadapost",
|
310
|
+
"rate_provider": "canadapost",
|
311
|
+
"service_name": "CANADAPOST PRIORITY",
|
312
|
+
},
|
313
|
+
"service": "canadapost_priority",
|
314
|
+
"selected_rate_id": ANY,
|
315
|
+
"test_mode": True,
|
316
|
+
}
|
317
|
+
|
318
|
+
SHIPPING_CANCEL_SUCCESS_RESPONSE = {
|
319
|
+
"messages": [],
|
320
|
+
"confirmation": {
|
321
|
+
"carrier_name": "canadapost",
|
322
|
+
"carrier_id": "canadapost",
|
323
|
+
"operation": "Cancel Shipment",
|
324
|
+
"success": True,
|
325
|
+
},
|
326
|
+
}
|
327
|
+
|
328
|
+
SHIPPING_CANCEL_FAILED_RESPONSE = {
|
329
|
+
"messages": [
|
330
|
+
{
|
331
|
+
"carrier_id": "canadapost",
|
332
|
+
"carrier_name": "canadapost",
|
333
|
+
"code": "404",
|
334
|
+
"message": "Not Found",
|
335
|
+
}
|
336
|
+
]
|
337
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import json
|
2
|
+
from unittest.mock import patch, ANY
|
3
|
+
from django.urls import reverse
|
4
|
+
from rest_framework import status
|
5
|
+
from karrio.core.models import TrackingDetails, TrackingEvent
|
6
|
+
from karrio.server.core.tests import APITestCase
|
7
|
+
|
8
|
+
|
9
|
+
class TestTracking(APITestCase):
|
10
|
+
def test_tracking_shipment(self):
|
11
|
+
url = reverse("karrio.server.proxy:get-tracking")
|
12
|
+
data = dict(tracking_number="1Z12345E6205277936", carrier_name="ups")
|
13
|
+
|
14
|
+
with patch("karrio.server.core.gateway.utils.identity") as mock:
|
15
|
+
mock.return_value = RETURNED_VALUE
|
16
|
+
response = self.client.post(f"{url}", data)
|
17
|
+
response_data = json.loads(response.content)
|
18
|
+
|
19
|
+
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
20
|
+
self.assertDictEqual(response_data, TRACKING_RESPONSE)
|
21
|
+
|
22
|
+
|
23
|
+
RETURNED_VALUE = [
|
24
|
+
[
|
25
|
+
TrackingDetails(
|
26
|
+
carrier_id="ups_package",
|
27
|
+
carrier_name="ups",
|
28
|
+
tracking_number="1Z12345E6205277936",
|
29
|
+
events=[
|
30
|
+
TrackingEvent(
|
31
|
+
code="KB",
|
32
|
+
date="2010-08-30",
|
33
|
+
description="UPS INTERNAL ACTIVITY CODE",
|
34
|
+
location="BONN",
|
35
|
+
time="10:39",
|
36
|
+
)
|
37
|
+
],
|
38
|
+
)
|
39
|
+
],
|
40
|
+
[],
|
41
|
+
]
|
42
|
+
|
43
|
+
TRACKING_RESPONSE = {
|
44
|
+
"messages": [],
|
45
|
+
"tracking": {
|
46
|
+
"id": ANY,
|
47
|
+
"carrier_name": "ups",
|
48
|
+
"carrier_id": "ups_package",
|
49
|
+
"tracking_number": "1Z12345E6205277936",
|
50
|
+
"images": None,
|
51
|
+
"info": {
|
52
|
+
"carrier_tracking_link": "https://www.ups.com/track?loc=en_US&requester=QUIC&tracknum=1Z12345E6205277936/trackdetails",
|
53
|
+
"customer_name": None,
|
54
|
+
"expected_delivery": None,
|
55
|
+
"note": None,
|
56
|
+
"order_date": None,
|
57
|
+
"order_id": None,
|
58
|
+
"package_weight": None,
|
59
|
+
"package_weight_unit": None,
|
60
|
+
"shipment_package_count": None,
|
61
|
+
"shipment_pickup_date": None,
|
62
|
+
"shipment_delivery_date": None,
|
63
|
+
"shipment_service": None,
|
64
|
+
"shipment_origin_country": None,
|
65
|
+
"shipment_origin_postal_code": None,
|
66
|
+
"shipment_destination_country": None,
|
67
|
+
"shipment_destination_postal_code": None,
|
68
|
+
"shipping_date": None,
|
69
|
+
"signed_by": None,
|
70
|
+
"source": "api",
|
71
|
+
},
|
72
|
+
"events": [
|
73
|
+
{
|
74
|
+
"date": "2010-08-30",
|
75
|
+
"description": "UPS INTERNAL ACTIVITY CODE",
|
76
|
+
"location": "BONN",
|
77
|
+
"code": "KB",
|
78
|
+
"time": "10:39",
|
79
|
+
"latitude": None,
|
80
|
+
"longitude": None,
|
81
|
+
}
|
82
|
+
],
|
83
|
+
"delivered": None,
|
84
|
+
"test_mode": True,
|
85
|
+
"status": "in_transit",
|
86
|
+
"estimated_delivery": ANY,
|
87
|
+
"meta": {"ext": "ups", "carrier": "ups"},
|
88
|
+
"object_type": "tracker",
|
89
|
+
"metadata": {},
|
90
|
+
"messages": [],
|
91
|
+
},
|
92
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import logging
|
2
|
+
import django.urls as urls
|
3
|
+
import rest_framework.status as status
|
4
|
+
import rest_framework.request as request
|
5
|
+
import rest_framework.response as response
|
6
|
+
|
7
|
+
import karrio.server.openapi as openapi
|
8
|
+
import karrio.server.core.views.api as api
|
9
|
+
import karrio.server.proxy.router as router
|
10
|
+
import karrio.server.core.gateway as gateway
|
11
|
+
import karrio.server.core.serializers as serializers
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
ENDPOINT_ID = "@@@$" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
15
|
+
|
16
|
+
DESCRIPTION = """
|
17
|
+
Some carriers require shipment manifests to be created for pickups and dropoff.
|
18
|
+
Creating a manifest for a shipment also kicks off billing as a commitment or confirmation of the shipment.
|
19
|
+
"""
|
20
|
+
|
21
|
+
|
22
|
+
class ManifestingAPI(api.APIView):
|
23
|
+
throttle_scope = "carrier_request"
|
24
|
+
|
25
|
+
@openapi.extend_schema(
|
26
|
+
tags=["Proxy"],
|
27
|
+
operation_id=f"{ENDPOINT_ID}generate_manifest",
|
28
|
+
extensions={"x-operationId": "generateManifest"},
|
29
|
+
summary="Create a manifest",
|
30
|
+
description=DESCRIPTION,
|
31
|
+
responses={
|
32
|
+
200: serializers.ManifestResponse(),
|
33
|
+
400: serializers.ErrorResponse(),
|
34
|
+
424: serializers.ErrorMessages(),
|
35
|
+
500: serializers.ErrorResponse(),
|
36
|
+
},
|
37
|
+
request=serializers.ManifestRequest(),
|
38
|
+
)
|
39
|
+
def post(self, request: request.Request):
|
40
|
+
payload = serializers.ManifestRequest.map(data=request.data).data
|
41
|
+
|
42
|
+
manifest = gateway.Manifests.create(payload, context=request)
|
43
|
+
|
44
|
+
return response.Response(
|
45
|
+
serializers.ManifestResponse(manifest).data, status=status.HTTP_200_OK
|
46
|
+
)
|
47
|
+
|
48
|
+
|
49
|
+
router.router.urls.append(
|
50
|
+
urls.path(
|
51
|
+
"proxy/manifest",
|
52
|
+
ManifestingAPI.as_view(),
|
53
|
+
name="shipment-manifest",
|
54
|
+
)
|
55
|
+
)
|
@@ -0,0 +1,151 @@
|
|
1
|
+
import logging
|
2
|
+
from django.urls import path
|
3
|
+
from rest_framework import status
|
4
|
+
from rest_framework.response import Response
|
5
|
+
from rest_framework.request import Request
|
6
|
+
|
7
|
+
import karrio.server.openapi as openapi
|
8
|
+
import karrio.server.core.utils as utils
|
9
|
+
import karrio.server.core.dataunits as dataunits
|
10
|
+
import karrio.server.providers.models as providers
|
11
|
+
from karrio.server.proxy.router import router
|
12
|
+
from karrio.server.core.gateway import Pickups
|
13
|
+
from karrio.server.core.views.api import APIView
|
14
|
+
from karrio.server.core.serializers import (
|
15
|
+
PickupCancelRequest,
|
16
|
+
PickupUpdateRequest,
|
17
|
+
OperationResponse,
|
18
|
+
PickupResponse,
|
19
|
+
PickupRequest,
|
20
|
+
ErrorResponse,
|
21
|
+
ErrorMessages,
|
22
|
+
)
|
23
|
+
|
24
|
+
logger = logging.getLogger(__name__)
|
25
|
+
ENDPOINT_ID = "@" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
26
|
+
|
27
|
+
|
28
|
+
class PickupSchedule(APIView):
|
29
|
+
throttle_scope = "carrier_request"
|
30
|
+
|
31
|
+
@openapi.extend_schema(
|
32
|
+
tags=["Proxy"],
|
33
|
+
operation_id=f"{ENDPOINT_ID}schedule_pickup",
|
34
|
+
extensions={"x-operationId": "pickupSchedule"},
|
35
|
+
summary="Schedule a pickup",
|
36
|
+
request=PickupRequest(),
|
37
|
+
responses={
|
38
|
+
201: PickupResponse(),
|
39
|
+
400: ErrorResponse(),
|
40
|
+
424: ErrorMessages(),
|
41
|
+
500: ErrorResponse(),
|
42
|
+
},
|
43
|
+
parameters=[
|
44
|
+
openapi.OpenApiParameter(
|
45
|
+
"carrier_name",
|
46
|
+
location=openapi.OpenApiParameter.PATH,
|
47
|
+
type=openapi.OpenApiTypes.STR,
|
48
|
+
enum=dataunits.CARRIER_NAMES,
|
49
|
+
),
|
50
|
+
],
|
51
|
+
)
|
52
|
+
def post(self, request: Request, carrier_name: str):
|
53
|
+
"""
|
54
|
+
Schedule one or many parcels pickup
|
55
|
+
"""
|
56
|
+
payload = PickupRequest.map(data=request.data).data
|
57
|
+
|
58
|
+
response = Pickups.schedule(payload, context=request, carrier_name=carrier_name)
|
59
|
+
|
60
|
+
return Response(PickupResponse(response).data, status=status.HTTP_201_CREATED)
|
61
|
+
|
62
|
+
|
63
|
+
class PickupUpdate(APIView):
|
64
|
+
throttle_scope = "carrier_request"
|
65
|
+
|
66
|
+
@openapi.extend_schema(
|
67
|
+
tags=["Proxy"],
|
68
|
+
operation_id=f"{ENDPOINT_ID}update_pickup",
|
69
|
+
extensions={"x-operationId": "pickupUpdate"},
|
70
|
+
summary="Update a pickup",
|
71
|
+
request=PickupUpdateRequest(),
|
72
|
+
responses={
|
73
|
+
200: PickupResponse(),
|
74
|
+
400: ErrorResponse(),
|
75
|
+
424: ErrorMessages(),
|
76
|
+
500: ErrorResponse(),
|
77
|
+
},
|
78
|
+
parameters=[
|
79
|
+
openapi.OpenApiParameter(
|
80
|
+
"carrier_name",
|
81
|
+
location=openapi.OpenApiParameter.PATH,
|
82
|
+
type=openapi.OpenApiTypes.STR,
|
83
|
+
enum=dataunits.CARRIER_NAMES,
|
84
|
+
),
|
85
|
+
],
|
86
|
+
)
|
87
|
+
def post(self, request: Request, carrier_name: str):
|
88
|
+
"""
|
89
|
+
Modify a scheduled pickup
|
90
|
+
"""
|
91
|
+
payload = PickupUpdateRequest.map(data=request.data).data
|
92
|
+
|
93
|
+
response = Pickups.update(payload, context=request, carrier_name=carrier_name)
|
94
|
+
|
95
|
+
return Response(PickupResponse(response).data, status=status.HTTP_200_OK)
|
96
|
+
|
97
|
+
|
98
|
+
class PickupCancel(APIView):
|
99
|
+
throttle_scope = "carrier_request"
|
100
|
+
|
101
|
+
@openapi.extend_schema(
|
102
|
+
tags=["Proxy"],
|
103
|
+
operation_id=f"{ENDPOINT_ID}cancel_pickup",
|
104
|
+
extensions={"x-operationId": "pickupCancel"},
|
105
|
+
summary="Cancel a pickup",
|
106
|
+
request=PickupCancelRequest(),
|
107
|
+
responses={
|
108
|
+
200: OperationResponse(),
|
109
|
+
400: ErrorResponse(),
|
110
|
+
424: ErrorMessages(),
|
111
|
+
500: ErrorResponse(),
|
112
|
+
},
|
113
|
+
parameters=[
|
114
|
+
openapi.OpenApiParameter(
|
115
|
+
"carrier_name",
|
116
|
+
location=openapi.OpenApiParameter.PATH,
|
117
|
+
type=openapi.OpenApiTypes.STR,
|
118
|
+
enum=dataunits.CARRIER_NAMES,
|
119
|
+
),
|
120
|
+
],
|
121
|
+
)
|
122
|
+
def post(self, request: Request, carrier_name: str):
|
123
|
+
"""
|
124
|
+
Cancel a pickup previously scheduled
|
125
|
+
"""
|
126
|
+
payload = PickupCancelRequest.map(data=request.data).data
|
127
|
+
|
128
|
+
response = Pickups.cancel(payload, context=request, carrier_name=carrier_name)
|
129
|
+
|
130
|
+
return Response(OperationResponse(response).data, status=status.HTTP_200_OK)
|
131
|
+
|
132
|
+
|
133
|
+
router.urls.append(
|
134
|
+
path(
|
135
|
+
"proxy/pickups/<carrier_name>", PickupSchedule.as_view(), name="pickup-schedule"
|
136
|
+
)
|
137
|
+
)
|
138
|
+
router.urls.append(
|
139
|
+
path(
|
140
|
+
"proxy/pickups/<carrier_name>/update",
|
141
|
+
PickupUpdate.as_view(),
|
142
|
+
name="pickup-details",
|
143
|
+
)
|
144
|
+
)
|
145
|
+
router.urls.append(
|
146
|
+
path(
|
147
|
+
"proxy/pickups/<carrier_name>/cancel",
|
148
|
+
PickupCancel.as_view(),
|
149
|
+
name="pickup-cancel",
|
150
|
+
)
|
151
|
+
)
|