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,57 @@
|
|
1
|
+
import logging
|
2
|
+
from django.urls import path
|
3
|
+
from rest_framework import status
|
4
|
+
from rest_framework.request import Request
|
5
|
+
from rest_framework.response import Response
|
6
|
+
|
7
|
+
from karrio.server.core.views.api import APIView
|
8
|
+
from karrio.server.core.serializers import (
|
9
|
+
RateRequest,
|
10
|
+
RateResponse,
|
11
|
+
ErrorResponse,
|
12
|
+
ErrorMessages,
|
13
|
+
)
|
14
|
+
from karrio.server.core.gateway import Rates
|
15
|
+
from karrio.server.proxy.router import router
|
16
|
+
import karrio.server.openapi as openapi
|
17
|
+
|
18
|
+
logger = logging.getLogger(__name__)
|
19
|
+
ENDPOINT_ID = "@@" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
20
|
+
|
21
|
+
DESCRIPTIONS = """
|
22
|
+
The Shipping process begins by fetching rates for your shipment.
|
23
|
+
Use this service to fetch a shipping rates available.
|
24
|
+
"""
|
25
|
+
|
26
|
+
|
27
|
+
class RateViewAPI(APIView):
|
28
|
+
throttle_scope = "carrier_request"
|
29
|
+
|
30
|
+
@openapi.extend_schema(
|
31
|
+
tags=["Proxy"],
|
32
|
+
operation_id=f"{ENDPOINT_ID}fetch_rates",
|
33
|
+
extensions={"x-operationId": "fetchRates"},
|
34
|
+
summary="Fetch shipment rates",
|
35
|
+
description=DESCRIPTIONS,
|
36
|
+
responses={
|
37
|
+
200: RateResponse(),
|
38
|
+
400: ErrorResponse(),
|
39
|
+
424: ErrorMessages(),
|
40
|
+
500: ErrorResponse(),
|
41
|
+
},
|
42
|
+
request=RateRequest(),
|
43
|
+
)
|
44
|
+
def post(self, request: Request):
|
45
|
+
payload = RateRequest.map(data=request.data).data
|
46
|
+
|
47
|
+
response = Rates.fetch(payload, context=request)
|
48
|
+
status_code = (
|
49
|
+
status.HTTP_207_MULTI_STATUS
|
50
|
+
if len(response.messages) > 0
|
51
|
+
else status.HTTP_200_OK
|
52
|
+
)
|
53
|
+
|
54
|
+
return Response(RateResponse(response).data, status=status_code)
|
55
|
+
|
56
|
+
|
57
|
+
router.urls.append(path("proxy/rates", RateViewAPI.as_view(), name="shipment-rates"))
|
@@ -0,0 +1,139 @@
|
|
1
|
+
import logging
|
2
|
+
from django.urls import path
|
3
|
+
from rest_framework import status
|
4
|
+
from rest_framework.request import Request
|
5
|
+
from rest_framework.reverse import reverse
|
6
|
+
from rest_framework.response import Response
|
7
|
+
|
8
|
+
import karrio.server.openapi as openapi
|
9
|
+
import karrio.server.serializers as serializers
|
10
|
+
import karrio.server.core.dataunits as dataunits
|
11
|
+
import karrio.server.providers.models as providers
|
12
|
+
from karrio.server.core.views.api import APIView
|
13
|
+
from karrio.server.proxy.router import router
|
14
|
+
from karrio.server.core.gateway import Shipments
|
15
|
+
from karrio.server.core.serializers import (
|
16
|
+
COUNTRIES,
|
17
|
+
ShippingRequest,
|
18
|
+
ShipmentCancelRequest,
|
19
|
+
ShipmentContent,
|
20
|
+
ShipmentDetails,
|
21
|
+
OperationResponse,
|
22
|
+
Address as BaseAddress,
|
23
|
+
ErrorResponse,
|
24
|
+
ErrorMessages,
|
25
|
+
)
|
26
|
+
|
27
|
+
ENDPOINT_ID = "@@@" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
28
|
+
logger = logging.getLogger(__name__)
|
29
|
+
|
30
|
+
|
31
|
+
class Address(BaseAddress):
|
32
|
+
city = serializers.CharField(required=True, help_text="The address city")
|
33
|
+
person_name = serializers.CharField(required=True, help_text="attention to")
|
34
|
+
country_code = serializers.ChoiceField(
|
35
|
+
required=True, choices=COUNTRIES, help_text="The address country code"
|
36
|
+
)
|
37
|
+
address_line1 = serializers.CharField(
|
38
|
+
required=True, help_text="The address line with street number"
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
class ShippingRequestValidation(ShippingRequest):
|
43
|
+
shipper = Address(
|
44
|
+
required=True, help_text="The origin address of the shipment (address from)"
|
45
|
+
)
|
46
|
+
recipient = Address(
|
47
|
+
required=True, help_text="The shipment destination address (address to)"
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
class ShippingResponse(serializers.EntitySerializer, ShipmentContent, ShipmentDetails):
|
52
|
+
object_type = serializers.CharField(
|
53
|
+
default="shipment", help_text="Specifies the object type"
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
class ShippingDetails(APIView):
|
58
|
+
throttle_scope = "carrier_request"
|
59
|
+
|
60
|
+
@openapi.extend_schema(
|
61
|
+
tags=["Proxy"],
|
62
|
+
operation_id=f"{ENDPOINT_ID}buy_label",
|
63
|
+
extensions={"x-operationId": "buyLabel"},
|
64
|
+
summary="Buy a shipment label",
|
65
|
+
request=ShippingRequest(),
|
66
|
+
responses={
|
67
|
+
200: ShippingResponse(),
|
68
|
+
400: ErrorResponse(),
|
69
|
+
424: ErrorMessages(),
|
70
|
+
500: ErrorResponse(),
|
71
|
+
},
|
72
|
+
)
|
73
|
+
def post(self, request: Request):
|
74
|
+
"""
|
75
|
+
Once the shipping rates are retrieved, provide the required info to
|
76
|
+
submit the shipment by specifying your preferred rate.
|
77
|
+
"""
|
78
|
+
payload = ShippingRequestValidation.map(data=request.data).data
|
79
|
+
|
80
|
+
response = Shipments.create(
|
81
|
+
payload,
|
82
|
+
resolve_tracking_url=(
|
83
|
+
lambda tracking_number, carrier_name: reverse(
|
84
|
+
"karrio.server.proxy:shipment-tracking",
|
85
|
+
kwargs=dict(
|
86
|
+
tracking_number=tracking_number, carrier_name=carrier_name
|
87
|
+
),
|
88
|
+
)
|
89
|
+
),
|
90
|
+
)
|
91
|
+
|
92
|
+
return Response(ShippingResponse(response).data, status=status.HTTP_200_OK)
|
93
|
+
|
94
|
+
|
95
|
+
class ShippingCancel(APIView):
|
96
|
+
throttle_scope = "carrier_request"
|
97
|
+
|
98
|
+
@openapi.extend_schema(
|
99
|
+
tags=["Proxy"],
|
100
|
+
operation_id=f"{ENDPOINT_ID}void_label",
|
101
|
+
extensions={"x-operationId": "voidLabel"},
|
102
|
+
summary="Void a shipment label",
|
103
|
+
request=ShipmentCancelRequest(),
|
104
|
+
responses={
|
105
|
+
202: OperationResponse(),
|
106
|
+
400: ErrorResponse(),
|
107
|
+
424: ErrorMessages(),
|
108
|
+
},
|
109
|
+
parameters=[
|
110
|
+
openapi.OpenApiParameter(
|
111
|
+
"carrier_name",
|
112
|
+
location=openapi.OpenApiParameter.PATH,
|
113
|
+
type=openapi.OpenApiTypes.STR,
|
114
|
+
enum=dataunits.CARRIER_NAMES,
|
115
|
+
),
|
116
|
+
],
|
117
|
+
)
|
118
|
+
def post(self, request: Request, carrier_name: str):
|
119
|
+
"""
|
120
|
+
Cancel a shipment and the label previously created
|
121
|
+
"""
|
122
|
+
payload = ShipmentCancelRequest.map(data=request.data).data
|
123
|
+
response = Shipments.cancel(payload, context=request, carrier_name=carrier_name)
|
124
|
+
|
125
|
+
return Response(
|
126
|
+
OperationResponse(response).data, status=status.HTTP_202_ACCEPTED
|
127
|
+
)
|
128
|
+
|
129
|
+
|
130
|
+
router.urls.append(
|
131
|
+
path("proxy/shipping", ShippingDetails.as_view(), name="shipping-request")
|
132
|
+
)
|
133
|
+
router.urls.append(
|
134
|
+
path(
|
135
|
+
"proxy/shipping/<carrier_name>/cancel",
|
136
|
+
ShippingCancel.as_view(),
|
137
|
+
name="shipping-cancel",
|
138
|
+
)
|
139
|
+
)
|
@@ -0,0 +1,165 @@
|
|
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.dataunits as dataunits
|
9
|
+
from karrio.server.core.views.api import APIView
|
10
|
+
from karrio.server.core.serializers import (
|
11
|
+
TrackingData,
|
12
|
+
TrackingResponse,
|
13
|
+
ErrorResponse,
|
14
|
+
ErrorMessages,
|
15
|
+
)
|
16
|
+
from karrio.server.core.gateway import Shipments
|
17
|
+
from karrio.server.proxy.router import router
|
18
|
+
|
19
|
+
logger = logging.getLogger(__name__)
|
20
|
+
ENDPOINT_ID = "@@@@" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
21
|
+
|
22
|
+
|
23
|
+
class TrackingAPIView(APIView):
|
24
|
+
throttle_scope = "carrier_request"
|
25
|
+
|
26
|
+
@openapi.extend_schema(
|
27
|
+
tags=["Proxy"],
|
28
|
+
operation_id=f"{ENDPOINT_ID}get_tracking",
|
29
|
+
extensions={"x-operationId": "getTracking"},
|
30
|
+
summary="Get tracking details",
|
31
|
+
request=TrackingData(),
|
32
|
+
responses={
|
33
|
+
200: TrackingResponse(),
|
34
|
+
400: ErrorResponse(),
|
35
|
+
424: ErrorMessages(),
|
36
|
+
500: ErrorResponse(),
|
37
|
+
},
|
38
|
+
parameters=[
|
39
|
+
openapi.OpenApiParameter(
|
40
|
+
"hub",
|
41
|
+
location=openapi.OpenApiParameter.QUERY,
|
42
|
+
type=openapi.OpenApiTypes.STR,
|
43
|
+
required=False,
|
44
|
+
),
|
45
|
+
],
|
46
|
+
)
|
47
|
+
def post(self, request: Request):
|
48
|
+
"""
|
49
|
+
You can track a shipment by specifying the carrier and the shipment tracking number.
|
50
|
+
"""
|
51
|
+
query = request.query_params
|
52
|
+
serializer = TrackingData(data=request.data)
|
53
|
+
serializer.is_valid(raise_exception=True)
|
54
|
+
data = serializer.validated_data
|
55
|
+
carrier_filter = {
|
56
|
+
**{k: v for k, v in query.items() if k != "hub"},
|
57
|
+
# If a hub is specified, use the hub as carrier to track the package
|
58
|
+
"carrier_name": (
|
59
|
+
query.get("hub") if "hub" in query else data["carrier_name"]
|
60
|
+
),
|
61
|
+
}
|
62
|
+
data = {
|
63
|
+
**data,
|
64
|
+
"tracking_numbers": [data["tracking_number"]],
|
65
|
+
"options": (
|
66
|
+
{data["tracking_number"]: {"carrier": data["carrier_name"]}}
|
67
|
+
if "hub" in query
|
68
|
+
else {}
|
69
|
+
),
|
70
|
+
}
|
71
|
+
|
72
|
+
response = Shipments.track(data, context=request, **carrier_filter)
|
73
|
+
|
74
|
+
return Response(
|
75
|
+
TrackingResponse(response).data,
|
76
|
+
status=(
|
77
|
+
status.HTTP_200_OK
|
78
|
+
if response.tracking is not None
|
79
|
+
else status.HTTP_404_NOT_FOUND
|
80
|
+
),
|
81
|
+
)
|
82
|
+
|
83
|
+
|
84
|
+
class TrackingAPI(APIView):
|
85
|
+
throttle_scope = "carrier_request"
|
86
|
+
logging_methods = ["GET"]
|
87
|
+
|
88
|
+
@openapi.extend_schema(
|
89
|
+
tags=["Proxy"],
|
90
|
+
operation_id=f"{ENDPOINT_ID}track_shipment",
|
91
|
+
extensions={"x-operationId": "trackShipment"},
|
92
|
+
summary="Track a shipment",
|
93
|
+
deprecated=True,
|
94
|
+
responses={
|
95
|
+
200: TrackingResponse(),
|
96
|
+
400: ErrorResponse(),
|
97
|
+
424: ErrorMessages(),
|
98
|
+
500: ErrorResponse(),
|
99
|
+
},
|
100
|
+
parameters=[
|
101
|
+
openapi.OpenApiParameter(
|
102
|
+
"carrier_name",
|
103
|
+
location=openapi.OpenApiParameter.PATH,
|
104
|
+
type=openapi.OpenApiTypes.STR,
|
105
|
+
enum=dataunits.NON_HUBS_CARRIERS,
|
106
|
+
required=True,
|
107
|
+
),
|
108
|
+
openapi.OpenApiParameter(
|
109
|
+
"tracking_number",
|
110
|
+
location=openapi.OpenApiParameter.PATH,
|
111
|
+
type=openapi.OpenApiTypes.STR,
|
112
|
+
required=True,
|
113
|
+
),
|
114
|
+
openapi.OpenApiParameter(
|
115
|
+
"hub",
|
116
|
+
location=openapi.OpenApiParameter.QUERY,
|
117
|
+
type=openapi.OpenApiTypes.STR,
|
118
|
+
required=False,
|
119
|
+
),
|
120
|
+
],
|
121
|
+
)
|
122
|
+
def get(self, request: Request, carrier_name: str, tracking_number: str):
|
123
|
+
"""
|
124
|
+
You can track a shipment by specifying the carrier and the shipment tracking number.
|
125
|
+
"""
|
126
|
+
query = request.query_params
|
127
|
+
carrier_filter = {
|
128
|
+
**{k: v for k, v in query.items() if k != "hub"},
|
129
|
+
# If a hub is specified, use the hub as carrier to track the package
|
130
|
+
"carrier_name": (query.get("hub") if "hub" in query else carrier_name),
|
131
|
+
}
|
132
|
+
data = {
|
133
|
+
"tracking_numbers": [tracking_number],
|
134
|
+
"options": (
|
135
|
+
{tracking_number: {"carrier": carrier_name}} if "hub" in query else {}
|
136
|
+
),
|
137
|
+
}
|
138
|
+
|
139
|
+
response = Shipments.track(data, context=request, **carrier_filter)
|
140
|
+
|
141
|
+
return Response(
|
142
|
+
TrackingResponse(response).data,
|
143
|
+
status=(
|
144
|
+
status.HTTP_200_OK
|
145
|
+
if response.tracking is not None
|
146
|
+
else status.HTTP_404_NOT_FOUND
|
147
|
+
),
|
148
|
+
)
|
149
|
+
|
150
|
+
|
151
|
+
router.urls.append(
|
152
|
+
path(
|
153
|
+
"proxy/tracking",
|
154
|
+
TrackingAPIView.as_view(),
|
155
|
+
name="get-tracking",
|
156
|
+
)
|
157
|
+
)
|
158
|
+
# Deprecated will be removed soon.
|
159
|
+
router.urls.append(
|
160
|
+
path(
|
161
|
+
"proxy/tracking/<str:carrier_name>/<str:tracking_number>",
|
162
|
+
TrackingAPI.as_view(),
|
163
|
+
name="shipment-tracking",
|
164
|
+
)
|
165
|
+
)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: karrio_server_proxy
|
3
|
+
Version: 2025.5rc1
|
4
|
+
Summary: Multi-carrier shipping API Proxy module
|
5
|
+
Author-email: karrio <hello@karrio.io>
|
6
|
+
License-Expression: Apache-2.0
|
7
|
+
Project-URL: Homepage, https://github.com/karrioapi/karrio
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Requires-Python: >=3.11
|
10
|
+
Description-Content-Type: text/markdown
|
11
|
+
Requires-Dist: karrio_server_core
|
12
|
+
|
13
|
+
# karrio.server.proxy
|
14
|
+
|
15
|
+
This package is a module of the [karrio](https://pypi.org/project/karrio.server) universal shipping API.
|
16
|
+
|
17
|
+
## Requirements
|
18
|
+
|
19
|
+
`Python 3.11+`
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
```bash
|
24
|
+
pip install karrio.server.proxy
|
25
|
+
```
|
26
|
+
|
27
|
+
Check the [karrio docs](https://docs.karrio.io) to get started.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
karrio/server/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
karrio/server/proxy/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
|
3
|
+
karrio/server/proxy/apps.py,sha256=jSzNhgTmq6Z5mIo-pv5jeEx2PJMI31oUGfBBLEO3p-M,99
|
4
|
+
karrio/server/proxy/models.py,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57
|
5
|
+
karrio/server/proxy/router.py,sha256=IBUR7rfBkdEHQzWxYOPcVSM8NBp3fte9G6Q5BVTUNNw,95
|
6
|
+
karrio/server/proxy/urls.py,sha256=DJFUFeaxOTyVNgu_A4opiX4-0gJlciRJNob-ScOkdV4,214
|
7
|
+
karrio/server/proxy/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
karrio/server/proxy/tests/__init__.py,sha256=m6Nms0Mg2SsrhNtWGC9Pr67qxpWos3WHipHfQZ6Zslw,263
|
9
|
+
karrio/server/proxy/tests/test_pickup.py,sha256=Z1P3a-ueLDkDPVnPEoPacHgtZXSgc6SCUYLpwv0DSzM,8817
|
10
|
+
karrio/server/proxy/tests/test_rating.py,sha256=ACc-9DnlND1eEg2QN_roeIG6kOeKSrlQVEtXrubeKyA,3151
|
11
|
+
karrio/server/proxy/tests/test_shipping.py,sha256=YG3uH5wL6bLEAO7iUQRsebKKuAFT23QegWRRyHgVOH0,10535
|
12
|
+
karrio/server/proxy/tests/test_tracking.py,sha256=aO4y6MqgANCGA2QN3a79ZxyAGfXcEXlKV6ghogGbO-w,2965
|
13
|
+
karrio/server/proxy/views/__init__.py,sha256=5W2I_z2WEgpnHzfrJWWMx0ptxGSGSHb3yO-ymYHggZQ,252
|
14
|
+
karrio/server/proxy/views/manifest.py,sha256=8O9H8iUUTpL0wPge0_j7vmEYGcaksUk_5bxBp9FNgjE,1793
|
15
|
+
karrio/server/proxy/views/pickup.py,sha256=GfmZBQMZSDDJKiHT-n3grIwgi02JMhnTQyaP7e4YcY8,4566
|
16
|
+
karrio/server/proxy/views/rating.py,sha256=7S2N6szPSjQsShnCgzPL8iZpibpw8jbaWgSY9DWXYQI,1721
|
17
|
+
karrio/server/proxy/views/shipping.py,sha256=gmO1OBVE8OgmyYIi_ksT_IARyqAeVKucUjMMiz_Vzyk,4459
|
18
|
+
karrio/server/proxy/views/tracking.py,sha256=HwCMinmiLsLuYyQtQpdmorFQ0WoNQyQ3uJ12_l6IwpQ,5227
|
19
|
+
karrio_server_proxy-2025.5rc1.dist-info/METADATA,sha256=D-e04IfxgPhkFTvaymOXcyaI73sLo1TXfoHvvvOivH8,680
|
20
|
+
karrio_server_proxy-2025.5rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
+
karrio_server_proxy-2025.5rc1.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
|
22
|
+
karrio_server_proxy-2025.5rc1.dist-info/RECORD,,
|