karrio-server-manager 2026.1__py3-none-any.whl → 2026.1.3__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/manager/migrations/0070_add_meta_and_product_fields.py +98 -0
- karrio/server/manager/migrations/0071_product_proxy.py +25 -0
- karrio/server/manager/migrations/0072_populate_json_fields.py +267 -0
- karrio/server/manager/migrations/0073_make_shipment_fk_nullable.py +36 -0
- karrio/server/manager/migrations/0074_clean_model_refactoring.py +207 -0
- karrio/server/manager/migrations/0075_populate_template_meta.py +69 -0
- karrio/server/manager/migrations/0076_remove_customs_model.py +66 -0
- karrio/server/manager/migrations/0077_add_carrier_snapshot_fields.py +83 -0
- karrio/server/manager/migrations/0078_populate_carrier_snapshots.py +112 -0
- karrio/server/manager/migrations/0079_remove_carrier_fk_fields.py +56 -0
- karrio/server/manager/migrations/0080_add_carrier_json_indexes.py +137 -0
- karrio/server/manager/migrations/0081_cleanup.py +62 -0
- karrio/server/manager/migrations/0082_shipment_fees.py +26 -0
- karrio/server/manager/models.py +421 -321
- karrio/server/manager/serializers/__init__.py +5 -4
- karrio/server/manager/serializers/address.py +8 -2
- karrio/server/manager/serializers/commodity.py +11 -4
- karrio/server/manager/serializers/document.py +29 -15
- karrio/server/manager/serializers/manifest.py +6 -3
- karrio/server/manager/serializers/parcel.py +5 -2
- karrio/server/manager/serializers/pickup.py +194 -67
- karrio/server/manager/serializers/shipment.py +232 -152
- karrio/server/manager/serializers/tracking.py +53 -12
- karrio/server/manager/tests/__init__.py +0 -1
- karrio/server/manager/tests/test_addresses.py +53 -0
- karrio/server/manager/tests/test_parcels.py +50 -0
- karrio/server/manager/tests/test_pickups.py +286 -50
- karrio/server/manager/tests/test_products.py +597 -0
- karrio/server/manager/tests/test_shipments.py +237 -92
- karrio/server/manager/tests/test_trackers.py +65 -1
- karrio/server/manager/views/__init__.py +1 -1
- karrio/server/manager/views/addresses.py +38 -2
- karrio/server/manager/views/documents.py +1 -1
- karrio/server/manager/views/parcels.py +25 -2
- karrio/server/manager/views/products.py +239 -0
- karrio/server/manager/views/trackers.py +69 -1
- {karrio_server_manager-2026.1.dist-info → karrio_server_manager-2026.1.3.dist-info}/METADATA +1 -1
- {karrio_server_manager-2026.1.dist-info → karrio_server_manager-2026.1.3.dist-info}/RECORD +40 -28
- {karrio_server_manager-2026.1.dist-info → karrio_server_manager-2026.1.3.dist-info}/WHEEL +1 -1
- karrio/server/manager/serializers/customs.py +0 -84
- karrio/server/manager/tests/test_custom_infos.py +0 -101
- karrio/server/manager/views/customs.py +0 -159
- {karrio_server_manager-2026.1.dist-info → karrio_server_manager-2026.1.3.dist-info}/top_level.txt +0 -0
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from unittest.mock import ANY
|
|
3
|
-
from django.urls import reverse
|
|
4
|
-
from rest_framework import status
|
|
5
|
-
from karrio.server.core.tests import APITestCase
|
|
6
|
-
from karrio.server.manager.models import Customs
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class TestCustomsInfo(APITestCase):
|
|
10
|
-
def test_create_customs(self):
|
|
11
|
-
url = reverse("karrio.server.manager:customs-list")
|
|
12
|
-
data = CUSTOMS_DATA
|
|
13
|
-
|
|
14
|
-
response = self.client.post(url, data)
|
|
15
|
-
response_data = json.loads(response.content)
|
|
16
|
-
|
|
17
|
-
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
|
18
|
-
self.assertDictEqual(response_data, CUSTOMS_RESPONSE)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class TestCustomsInfoDetails(APITestCase):
|
|
22
|
-
def setUp(self) -> None:
|
|
23
|
-
super().setUp()
|
|
24
|
-
self.customs: Customs = Customs.objects.create(**{"created_by": self.user})
|
|
25
|
-
|
|
26
|
-
def test_update_customs(self):
|
|
27
|
-
url = reverse(
|
|
28
|
-
"karrio.server.manager:customs-details", kwargs=dict(pk=self.customs.pk)
|
|
29
|
-
)
|
|
30
|
-
data = CUSTOMS_UPDATE_DATA
|
|
31
|
-
|
|
32
|
-
response = self.client.patch(url, data)
|
|
33
|
-
response_data = json.loads(response.content)
|
|
34
|
-
|
|
35
|
-
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
36
|
-
self.assertDictEqual(response_data, CUSTOMS_UPDATE_RESPONSE)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
CUSTOMS_DATA = {
|
|
40
|
-
"incoterm": "DDU",
|
|
41
|
-
"commodities": [
|
|
42
|
-
{"title": "cn", "weight": 4.0, "weight_unit": "KG", "sku": "cc"},
|
|
43
|
-
],
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
CUSTOMS_RESPONSE = {
|
|
47
|
-
"certify": None,
|
|
48
|
-
"commercial_invoice": None,
|
|
49
|
-
"commodities": [
|
|
50
|
-
{
|
|
51
|
-
"description": None,
|
|
52
|
-
"title": "cn",
|
|
53
|
-
"id": ANY,
|
|
54
|
-
"object_type": "commodity",
|
|
55
|
-
"origin_country": None,
|
|
56
|
-
"parent_id": None,
|
|
57
|
-
"product_id": None,
|
|
58
|
-
"product_url": None,
|
|
59
|
-
"image_url": None,
|
|
60
|
-
"variant_id": None,
|
|
61
|
-
"quantity": 1,
|
|
62
|
-
"metadata": {},
|
|
63
|
-
"sku": "cc",
|
|
64
|
-
"hs_code": None,
|
|
65
|
-
"value_amount": None,
|
|
66
|
-
"value_currency": None,
|
|
67
|
-
"weight": 4.0,
|
|
68
|
-
"weight_unit": "KG",
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
"content_description": None,
|
|
72
|
-
"content_type": None,
|
|
73
|
-
"duty": None,
|
|
74
|
-
"duty_billing_address": None,
|
|
75
|
-
"id": ANY,
|
|
76
|
-
"object_type": "customs_info",
|
|
77
|
-
"incoterm": "DDU",
|
|
78
|
-
"invoice": None,
|
|
79
|
-
"invoice_date": None,
|
|
80
|
-
"options": {},
|
|
81
|
-
"signer": None,
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
CUSTOMS_UPDATE_DATA = {"incoterm": "DDP"}
|
|
85
|
-
|
|
86
|
-
CUSTOMS_UPDATE_RESPONSE = {
|
|
87
|
-
"certify": None,
|
|
88
|
-
"commercial_invoice": None,
|
|
89
|
-
"commodities": [],
|
|
90
|
-
"content_description": None,
|
|
91
|
-
"content_type": None,
|
|
92
|
-
"duty": None,
|
|
93
|
-
"duty_billing_address": None,
|
|
94
|
-
"id": ANY,
|
|
95
|
-
"object_type": "customs_info",
|
|
96
|
-
"incoterm": "DDP",
|
|
97
|
-
"invoice": None,
|
|
98
|
-
"invoice_date": None,
|
|
99
|
-
"options": {},
|
|
100
|
-
"signer": None,
|
|
101
|
-
}
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
|
|
3
|
-
from django.urls import path
|
|
4
|
-
from rest_framework import status
|
|
5
|
-
from rest_framework.request import Request
|
|
6
|
-
from rest_framework.response import Response
|
|
7
|
-
from rest_framework.pagination import LimitOffsetPagination
|
|
8
|
-
|
|
9
|
-
from karrio.server.core.views.api import GenericAPIView, APIView
|
|
10
|
-
from karrio.server.manager.serializers import (
|
|
11
|
-
PaginatedResult,
|
|
12
|
-
ErrorResponse,
|
|
13
|
-
CustomsData,
|
|
14
|
-
Customs,
|
|
15
|
-
CustomsSerializer,
|
|
16
|
-
can_mutate_customs,
|
|
17
|
-
)
|
|
18
|
-
from karrio.server.manager.router import router
|
|
19
|
-
import karrio.server.manager.models as models
|
|
20
|
-
import karrio.server.openapi as openapi
|
|
21
|
-
|
|
22
|
-
ENDPOINT_ID = "$$" # This endpoint id is used to make operation ids unique make sure not to duplicate
|
|
23
|
-
logger = logging.getLogger(__name__)
|
|
24
|
-
CustomsInfoList = PaginatedResult("CustomsList", Customs)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class CustomsList(GenericAPIView):
|
|
28
|
-
queryset = models.Customs.objects
|
|
29
|
-
pagination_class = type(
|
|
30
|
-
"CustomPagination", (LimitOffsetPagination,), dict(default_limit=20)
|
|
31
|
-
)
|
|
32
|
-
serializer_class = CustomsInfoList
|
|
33
|
-
|
|
34
|
-
@openapi.extend_schema(
|
|
35
|
-
exclude=True,
|
|
36
|
-
tags=["Customs"],
|
|
37
|
-
operation_id=f"{ENDPOINT_ID}list",
|
|
38
|
-
extensions={"x-operationId": "listCustomsInfo"},
|
|
39
|
-
summary="List all customs info",
|
|
40
|
-
responses={
|
|
41
|
-
200: CustomsInfoList(),
|
|
42
|
-
404: ErrorResponse(),
|
|
43
|
-
500: ErrorResponse(),
|
|
44
|
-
},
|
|
45
|
-
)
|
|
46
|
-
def get(self, request: Request):
|
|
47
|
-
"""
|
|
48
|
-
Retrieve all stored customs declarations.
|
|
49
|
-
"""
|
|
50
|
-
customs_info = models.Customs.access_by(request).filter(
|
|
51
|
-
**{
|
|
52
|
-
f"{prop}__isnull": True
|
|
53
|
-
for prop in models.Customs.HIDDEN_PROPS
|
|
54
|
-
if prop != "org"
|
|
55
|
-
}
|
|
56
|
-
)
|
|
57
|
-
serializer = Customs(customs_info, many=True)
|
|
58
|
-
response = self.paginate_queryset(serializer.data)
|
|
59
|
-
return self.get_paginated_response(response)
|
|
60
|
-
|
|
61
|
-
@openapi.extend_schema(
|
|
62
|
-
exclude=True,
|
|
63
|
-
tags=["Customs"],
|
|
64
|
-
operation_id=f"{ENDPOINT_ID}create",
|
|
65
|
-
extensions={"x-operationId": "createCustomsInfo"},
|
|
66
|
-
summary="Create a customs info",
|
|
67
|
-
request=CustomsData(),
|
|
68
|
-
responses={
|
|
69
|
-
201: Customs(),
|
|
70
|
-
400: ErrorResponse(),
|
|
71
|
-
500: ErrorResponse(),
|
|
72
|
-
},
|
|
73
|
-
)
|
|
74
|
-
def post(self, request: Request):
|
|
75
|
-
"""
|
|
76
|
-
Create a new customs declaration.
|
|
77
|
-
"""
|
|
78
|
-
customs = (
|
|
79
|
-
CustomsSerializer.map(data=request.data, context=request).save().instance
|
|
80
|
-
)
|
|
81
|
-
return Response(Customs(customs).data, status=status.HTTP_201_CREATED)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class CustomsDetail(APIView):
|
|
85
|
-
|
|
86
|
-
@openapi.extend_schema(
|
|
87
|
-
exclude=True,
|
|
88
|
-
tags=["Customs"],
|
|
89
|
-
operation_id=f"{ENDPOINT_ID}retrieve",
|
|
90
|
-
extensions={"x-operationId": "retrieveCustomsInfo"},
|
|
91
|
-
summary="Retrieve a customs info",
|
|
92
|
-
responses={
|
|
93
|
-
200: Customs(),
|
|
94
|
-
404: ErrorResponse(),
|
|
95
|
-
500: ErrorResponse(),
|
|
96
|
-
},
|
|
97
|
-
)
|
|
98
|
-
def get(self, request: Request, pk: str):
|
|
99
|
-
"""
|
|
100
|
-
Retrieve customs declaration.
|
|
101
|
-
"""
|
|
102
|
-
address = models.Customs.access_by(request).get(pk=pk)
|
|
103
|
-
return Response(Customs(address).data)
|
|
104
|
-
|
|
105
|
-
@openapi.extend_schema(
|
|
106
|
-
exclude=True,
|
|
107
|
-
tags=["Customs"],
|
|
108
|
-
operation_id=f"{ENDPOINT_ID}update",
|
|
109
|
-
extensions={"x-operationId": "updateCustomsInfo"},
|
|
110
|
-
summary="Update a customs info",
|
|
111
|
-
request=CustomsData(),
|
|
112
|
-
responses={
|
|
113
|
-
200: Customs(),
|
|
114
|
-
400: ErrorResponse(),
|
|
115
|
-
404: ErrorResponse(),
|
|
116
|
-
409: ErrorResponse(),
|
|
117
|
-
500: ErrorResponse(),
|
|
118
|
-
},
|
|
119
|
-
)
|
|
120
|
-
def patch(self, request: Request, pk: str):
|
|
121
|
-
"""
|
|
122
|
-
modify an existing customs declaration.
|
|
123
|
-
"""
|
|
124
|
-
customs = models.Customs.access_by(request).get(pk=pk)
|
|
125
|
-
can_mutate_customs(customs)
|
|
126
|
-
|
|
127
|
-
CustomsSerializer.map(customs, data=request.data, context=request).save()
|
|
128
|
-
|
|
129
|
-
return Response(Customs(customs).data)
|
|
130
|
-
|
|
131
|
-
@openapi.extend_schema(
|
|
132
|
-
exclude=True,
|
|
133
|
-
tags=["Customs"],
|
|
134
|
-
operation_id=f"{ENDPOINT_ID}discard",
|
|
135
|
-
extensions={"x-operationId": "discardCustomsInfo"},
|
|
136
|
-
summary="Discard a customs info",
|
|
137
|
-
responses={
|
|
138
|
-
200: Customs(),
|
|
139
|
-
404: ErrorResponse(),
|
|
140
|
-
409: ErrorResponse(),
|
|
141
|
-
500: ErrorResponse(),
|
|
142
|
-
},
|
|
143
|
-
)
|
|
144
|
-
def delete(self, request: Request, pk: str):
|
|
145
|
-
"""
|
|
146
|
-
Discard a customs declaration.
|
|
147
|
-
"""
|
|
148
|
-
customs = models.Customs.access_by(request).get(pk=pk)
|
|
149
|
-
can_mutate_customs(customs)
|
|
150
|
-
|
|
151
|
-
customs.delete(keep_parents=True)
|
|
152
|
-
|
|
153
|
-
return Response(Customs(customs).data)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
router.urls.append(path("customs_info", CustomsList.as_view(), name="customs-list"))
|
|
157
|
-
router.urls.append(
|
|
158
|
-
path("customs_info/<str:pk>", CustomsDetail.as_view(), name="customs-details")
|
|
159
|
-
)
|
{karrio_server_manager-2026.1.dist-info → karrio_server_manager-2026.1.3.dist-info}/top_level.txt
RENAMED
|
File without changes
|