karrio-server-manager 2025.5rc36__py3-none-any.whl → 2025.5.1__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/serializers/shipment.py +39 -5
- karrio/server/manager/tests/test_errors.py +88 -0
- karrio/server/manager/tests/test_shipments.py +192 -0
- karrio/server/manager/views/manifests.py +11 -13
- karrio/server/manager/views/shipments.py +9 -3
- {karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/METADATA +2 -2
- {karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/RECORD +9 -8
- {karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/WHEEL +0 -0
- {karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/top_level.txt +0 -0
|
@@ -48,6 +48,7 @@ from karrio.server.manager.serializers.customs import CustomsSerializer
|
|
|
48
48
|
from karrio.server.manager.serializers.parcel import ParcelSerializer
|
|
49
49
|
from karrio.server.manager.serializers.rate import RateSerializer
|
|
50
50
|
import karrio.server.manager.models as models
|
|
51
|
+
|
|
51
52
|
DEFAULT_CARRIER_FILTER: typing.Any = dict(active=True, capability="shipping")
|
|
52
53
|
|
|
53
54
|
|
|
@@ -288,7 +289,16 @@ class ShipmentSerializer(ShipmentData):
|
|
|
288
289
|
|
|
289
290
|
|
|
290
291
|
class ShipmentPurchaseData(Serializer):
|
|
291
|
-
selected_rate_id = CharField(
|
|
292
|
+
selected_rate_id = CharField(
|
|
293
|
+
required=False,
|
|
294
|
+
allow_null=True,
|
|
295
|
+
help_text="The shipment selected rate.",
|
|
296
|
+
)
|
|
297
|
+
service = CharField(
|
|
298
|
+
required=False,
|
|
299
|
+
allow_null=True,
|
|
300
|
+
help_text="The carrier service to use for the shipment (alternative to selected_rate_id).",
|
|
301
|
+
)
|
|
292
302
|
label_type = ChoiceField(
|
|
293
303
|
required=False,
|
|
294
304
|
choices=LABEL_TYPES,
|
|
@@ -306,6 +316,15 @@ class ShipmentPurchaseData(Serializer):
|
|
|
306
316
|
required=False, help_text="User metadata for the shipment"
|
|
307
317
|
)
|
|
308
318
|
|
|
319
|
+
def validate(self, data):
|
|
320
|
+
if not data.get("selected_rate_id") and not data.get("service"):
|
|
321
|
+
raise exceptions.APIException(
|
|
322
|
+
"Either 'selected_rate_id' or 'service' must be provided.",
|
|
323
|
+
code="validation_error",
|
|
324
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
|
325
|
+
)
|
|
326
|
+
return data
|
|
327
|
+
|
|
309
328
|
|
|
310
329
|
class ShipmentUpdateData(validators.OptionDefaultSerializer):
|
|
311
330
|
label_type = ChoiceField(
|
|
@@ -792,9 +811,15 @@ def create_shipment_tracker(shipment: typing.Optional[models.Shipment], context)
|
|
|
792
811
|
)
|
|
793
812
|
tracker.save()
|
|
794
813
|
link_org(tracker, context)
|
|
795
|
-
logger.info(
|
|
814
|
+
logger.info(
|
|
815
|
+
"Successfully added a tracker to the shipment", shipment_id=shipment.id
|
|
816
|
+
)
|
|
796
817
|
except Exception as e:
|
|
797
|
-
logger.exception(
|
|
818
|
+
logger.exception(
|
|
819
|
+
"Failed to create new label tracker",
|
|
820
|
+
error=str(e),
|
|
821
|
+
shipment_id=shipment.id,
|
|
822
|
+
)
|
|
798
823
|
|
|
799
824
|
# Update shipment tracking url if different from the current one
|
|
800
825
|
try:
|
|
@@ -815,7 +840,12 @@ def create_shipment_tracker(shipment: typing.Optional[models.Shipment], context)
|
|
|
815
840
|
shipment.tracking_url = tracking_url
|
|
816
841
|
shipment.save(update_fields=["tracking_url"])
|
|
817
842
|
except Exception as e:
|
|
818
|
-
logger.exception(
|
|
843
|
+
logger.exception(
|
|
844
|
+
"Failed to update shipment tracking url",
|
|
845
|
+
error=str(e),
|
|
846
|
+
shipment_id=shipment.id,
|
|
847
|
+
tracking_number=shipment.tracking_number,
|
|
848
|
+
)
|
|
819
849
|
|
|
820
850
|
|
|
821
851
|
def generate_custom_invoice(template: str, shipment: models.Shipment, **kwargs):
|
|
@@ -843,7 +873,11 @@ def generate_custom_invoice(template: str, shipment: models.Shipment, **kwargs):
|
|
|
843
873
|
shipment.invoice = document["doc_file"]
|
|
844
874
|
shipment.save(update_fields=["invoice"])
|
|
845
875
|
|
|
846
|
-
logger.info(
|
|
876
|
+
logger.info(
|
|
877
|
+
"Custom document successfully generated",
|
|
878
|
+
shipment_id=shipment.id,
|
|
879
|
+
template=template,
|
|
880
|
+
)
|
|
847
881
|
|
|
848
882
|
return document
|
|
849
883
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from django.urls import reverse
|
|
3
|
+
from rest_framework import status
|
|
4
|
+
from karrio.server.core.tests import APITestCase
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestNotFoundErrors(APITestCase):
|
|
8
|
+
def test_address_not_found_returns_resource_name(self):
|
|
9
|
+
url = reverse(
|
|
10
|
+
"karrio.server.manager:address-details",
|
|
11
|
+
kwargs=dict(pk="nonexistent_id"),
|
|
12
|
+
)
|
|
13
|
+
response = self.client.get(url)
|
|
14
|
+
response_data = json.loads(response.content)
|
|
15
|
+
|
|
16
|
+
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
17
|
+
self.assertDictEqual(
|
|
18
|
+
response_data,
|
|
19
|
+
{"errors": [{"code": "not_found", "message": "Address not found"}]},
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
def test_parcel_not_found_returns_resource_name(self):
|
|
23
|
+
url = reverse(
|
|
24
|
+
"karrio.server.manager:parcel-details",
|
|
25
|
+
kwargs=dict(pk="nonexistent_id"),
|
|
26
|
+
)
|
|
27
|
+
response = self.client.get(url)
|
|
28
|
+
response_data = json.loads(response.content)
|
|
29
|
+
|
|
30
|
+
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
31
|
+
self.assertDictEqual(
|
|
32
|
+
response_data,
|
|
33
|
+
{"errors": [{"code": "not_found", "message": "Parcel not found"}]},
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def test_shipment_not_found_returns_resource_name(self):
|
|
37
|
+
url = reverse(
|
|
38
|
+
"karrio.server.manager:shipment-details",
|
|
39
|
+
kwargs=dict(pk="nonexistent_id"),
|
|
40
|
+
)
|
|
41
|
+
response = self.client.get(url)
|
|
42
|
+
response_data = json.loads(response.content)
|
|
43
|
+
|
|
44
|
+
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
45
|
+
self.assertDictEqual(
|
|
46
|
+
response_data,
|
|
47
|
+
{"errors": [{"code": "not_found", "message": "Shipment not found"}]},
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def test_customs_not_found_returns_resource_name(self):
|
|
51
|
+
url = reverse(
|
|
52
|
+
"karrio.server.manager:customs-details",
|
|
53
|
+
kwargs=dict(pk="nonexistent_id"),
|
|
54
|
+
)
|
|
55
|
+
response = self.client.get(url)
|
|
56
|
+
response_data = json.loads(response.content)
|
|
57
|
+
|
|
58
|
+
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
|
59
|
+
self.assertDictEqual(
|
|
60
|
+
response_data,
|
|
61
|
+
{"errors": [{"code": "not_found", "message": "Customs not found"}]},
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class TestValidationErrors(APITestCase):
|
|
66
|
+
def test_shipment_validation_error_format(self):
|
|
67
|
+
url = reverse("karrio.server.manager:shipment-list")
|
|
68
|
+
data = {
|
|
69
|
+
"shipper": {},
|
|
70
|
+
"recipient": {},
|
|
71
|
+
"parcels": [],
|
|
72
|
+
}
|
|
73
|
+
response = self.client.post(url, data, format="json")
|
|
74
|
+
response_data = json.loads(response.content)
|
|
75
|
+
|
|
76
|
+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
77
|
+
self.assertIn("errors", response_data)
|
|
78
|
+
self.assertTrue(len(response_data["errors"]) > 0)
|
|
79
|
+
|
|
80
|
+
def test_address_validation_error_format(self):
|
|
81
|
+
url = reverse("karrio.server.manager:address-list")
|
|
82
|
+
data = {"country_code": "INVALID"}
|
|
83
|
+
response = self.client.post(url, data, format="json")
|
|
84
|
+
response_data = json.loads(response.content)
|
|
85
|
+
|
|
86
|
+
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
87
|
+
self.assertIn("errors", response_data)
|
|
88
|
+
self.assertTrue(len(response_data["errors"]) > 0)
|
|
@@ -831,3 +831,195 @@ CANCEL_PURCHASED_RESPONSE = {
|
|
|
831
831
|
"label_url": None,
|
|
832
832
|
"invoice_url": None,
|
|
833
833
|
}
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
class TestShipmentPurchaseWithAlternativeServices(TestShipmentFixture):
|
|
837
|
+
def setUp(self) -> None:
|
|
838
|
+
super().setUp()
|
|
839
|
+
carrier = providers.Carrier.objects.get(carrier_id="canadapost")
|
|
840
|
+
# Rates have "canadapost_regular_parcel" but we'll request "canadapost_priority"
|
|
841
|
+
self.shipment.rates = [
|
|
842
|
+
{
|
|
843
|
+
"id": "rat_alt_service_test",
|
|
844
|
+
"carrier_id": "canadapost",
|
|
845
|
+
"carrier_name": "canadapost",
|
|
846
|
+
"currency": "CAD",
|
|
847
|
+
"estimated_delivery": None,
|
|
848
|
+
"extra_charges": [
|
|
849
|
+
{"amount": 50.00, "currency": "CAD", "name": "Base charge"},
|
|
850
|
+
],
|
|
851
|
+
"service": "canadapost_regular_parcel",
|
|
852
|
+
"total_charge": 50.00,
|
|
853
|
+
"transit_days": 5,
|
|
854
|
+
"test_mode": True,
|
|
855
|
+
"meta": {
|
|
856
|
+
"rate_provider": "canadapost",
|
|
857
|
+
"service_name": "CANADAPOST REGULAR PARCEL",
|
|
858
|
+
"carrier_connection_id": carrier.pk,
|
|
859
|
+
},
|
|
860
|
+
}
|
|
861
|
+
]
|
|
862
|
+
self.shipment.options = {"has_alternative_services": True}
|
|
863
|
+
self.shipment.save()
|
|
864
|
+
|
|
865
|
+
def test_purchase_with_alternative_service(self):
|
|
866
|
+
"""
|
|
867
|
+
Test that when canadapost_priority is requested but only canadapost_regular_parcel
|
|
868
|
+
is in rates, the purchase proceeds with has_alternative_services=True,
|
|
869
|
+
delegating service resolution to the carrier.
|
|
870
|
+
"""
|
|
871
|
+
url = reverse(
|
|
872
|
+
"karrio.server.manager:shipment-purchase",
|
|
873
|
+
kwargs=dict(pk=self.shipment.pk),
|
|
874
|
+
)
|
|
875
|
+
data = {"service": "canadapost_priority"}
|
|
876
|
+
|
|
877
|
+
with patch("karrio.server.core.gateway.utils.identity") as mock:
|
|
878
|
+
mock.return_value = CREATED_SHIPMENT_RESPONSE
|
|
879
|
+
response = self.client.post(url, data)
|
|
880
|
+
response_data = json.loads(response.content)
|
|
881
|
+
|
|
882
|
+
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
|
883
|
+
self.assertDictEqual(response_data, ALTERNATIVE_SERVICE_PURCHASED_SHIPMENT)
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
ALTERNATIVE_SERVICE_PURCHASED_SHIPMENT = {
|
|
887
|
+
"id": ANY,
|
|
888
|
+
"object_type": "shipment",
|
|
889
|
+
"tracking_url": "/v1/trackers/canadapost/123456789012",
|
|
890
|
+
"shipper": {
|
|
891
|
+
"id": ANY,
|
|
892
|
+
"postal_code": "E1C4Z8",
|
|
893
|
+
"city": "Moncton",
|
|
894
|
+
"federal_tax_id": None,
|
|
895
|
+
"state_tax_id": None,
|
|
896
|
+
"person_name": "John Poop",
|
|
897
|
+
"company_name": "A corp.",
|
|
898
|
+
"country_code": "CA",
|
|
899
|
+
"email": None,
|
|
900
|
+
"phone_number": "514 000 0000",
|
|
901
|
+
"state_code": "NB",
|
|
902
|
+
"street_number": None,
|
|
903
|
+
"residential": False,
|
|
904
|
+
"address_line1": "125 Church St",
|
|
905
|
+
"address_line2": None,
|
|
906
|
+
"validate_location": False,
|
|
907
|
+
"object_type": "address",
|
|
908
|
+
"validation": None,
|
|
909
|
+
},
|
|
910
|
+
"recipient": {
|
|
911
|
+
"id": ANY,
|
|
912
|
+
"postal_code": "V6M2V9",
|
|
913
|
+
"city": "Vancouver",
|
|
914
|
+
"federal_tax_id": None,
|
|
915
|
+
"state_tax_id": None,
|
|
916
|
+
"person_name": "Jane Doe",
|
|
917
|
+
"company_name": "B corp.",
|
|
918
|
+
"country_code": "CA",
|
|
919
|
+
"email": None,
|
|
920
|
+
"phone_number": "514 000 9999",
|
|
921
|
+
"state_code": "BC",
|
|
922
|
+
"street_number": None,
|
|
923
|
+
"residential": False,
|
|
924
|
+
"address_line1": "5840 Oak St",
|
|
925
|
+
"address_line2": None,
|
|
926
|
+
"validate_location": False,
|
|
927
|
+
"object_type": "address",
|
|
928
|
+
"validation": None,
|
|
929
|
+
},
|
|
930
|
+
"parcels": [
|
|
931
|
+
{
|
|
932
|
+
"id": ANY,
|
|
933
|
+
"weight": 1.0,
|
|
934
|
+
"width": None,
|
|
935
|
+
"height": None,
|
|
936
|
+
"length": None,
|
|
937
|
+
"packaging_type": None,
|
|
938
|
+
"package_preset": "canadapost_corrugated_small_box",
|
|
939
|
+
"description": None,
|
|
940
|
+
"content": None,
|
|
941
|
+
"is_document": False,
|
|
942
|
+
"weight_unit": "KG",
|
|
943
|
+
"dimension_unit": None,
|
|
944
|
+
"items": [],
|
|
945
|
+
"freight_class": None,
|
|
946
|
+
"reference_number": ANY,
|
|
947
|
+
"object_type": "parcel",
|
|
948
|
+
"options": {},
|
|
949
|
+
}
|
|
950
|
+
],
|
|
951
|
+
"services": [],
|
|
952
|
+
"options": {"has_alternative_services": True, "shipping_date": ANY, "shipment_date": ANY},
|
|
953
|
+
"payment": {"paid_by": "sender", "currency": "CAD", "account_number": None},
|
|
954
|
+
"return_address": None,
|
|
955
|
+
"billing_address": None,
|
|
956
|
+
"customs": None,
|
|
957
|
+
"rates": [
|
|
958
|
+
{
|
|
959
|
+
"id": ANY,
|
|
960
|
+
"object_type": "rate",
|
|
961
|
+
"carrier_name": "canadapost",
|
|
962
|
+
"carrier_id": "canadapost",
|
|
963
|
+
"currency": "CAD",
|
|
964
|
+
"estimated_delivery": ANY,
|
|
965
|
+
"service": "canadapost_regular_parcel",
|
|
966
|
+
"total_charge": 50.00,
|
|
967
|
+
"transit_days": 5,
|
|
968
|
+
"extra_charges": [
|
|
969
|
+
{"name": "Base charge", "amount": 50.00, "currency": "CAD", "id": None},
|
|
970
|
+
],
|
|
971
|
+
"meta": {
|
|
972
|
+
"service_name": "CANADAPOST REGULAR PARCEL",
|
|
973
|
+
"rate_provider": "canadapost",
|
|
974
|
+
"carrier_connection_id": ANY,
|
|
975
|
+
},
|
|
976
|
+
"test_mode": True,
|
|
977
|
+
}
|
|
978
|
+
],
|
|
979
|
+
"reference": None,
|
|
980
|
+
"label_type": "PDF",
|
|
981
|
+
"carrier_ids": [],
|
|
982
|
+
"tracker_id": ANY,
|
|
983
|
+
"created_at": ANY,
|
|
984
|
+
"metadata": {},
|
|
985
|
+
"messages": [],
|
|
986
|
+
"status": "purchased",
|
|
987
|
+
"carrier_name": "canadapost",
|
|
988
|
+
"carrier_id": "canadapost",
|
|
989
|
+
"tracking_number": "123456789012",
|
|
990
|
+
"shipment_identifier": "123456789012",
|
|
991
|
+
"selected_rate": {
|
|
992
|
+
"id": ANY,
|
|
993
|
+
"object_type": "rate",
|
|
994
|
+
"carrier_name": "canadapost",
|
|
995
|
+
"carrier_id": "canadapost",
|
|
996
|
+
"currency": "CAD",
|
|
997
|
+
"estimated_delivery": ANY,
|
|
998
|
+
"service": "canadapost_priority",
|
|
999
|
+
"total_charge": 50.00,
|
|
1000
|
+
"transit_days": 5,
|
|
1001
|
+
"extra_charges": [
|
|
1002
|
+
{"name": "Base charge", "amount": 50.00, "currency": "CAD", "id": None},
|
|
1003
|
+
],
|
|
1004
|
+
"meta": {
|
|
1005
|
+
"ext": "canadapost",
|
|
1006
|
+
"carrier": "canadapost",
|
|
1007
|
+
"service_name": "CANADAPOST REGULAR PARCEL",
|
|
1008
|
+
"rate_provider": "canadapost",
|
|
1009
|
+
"carrier_connection_id": ANY,
|
|
1010
|
+
"has_alternative_services": True,
|
|
1011
|
+
},
|
|
1012
|
+
"test_mode": True,
|
|
1013
|
+
},
|
|
1014
|
+
"meta": {
|
|
1015
|
+
"ext": "canadapost",
|
|
1016
|
+
"carrier": "canadapost",
|
|
1017
|
+
"rate_provider": "canadapost",
|
|
1018
|
+
"service_name": "CANADAPOST PRIORITY",
|
|
1019
|
+
},
|
|
1020
|
+
"service": "canadapost_priority",
|
|
1021
|
+
"selected_rate_id": ANY,
|
|
1022
|
+
"test_mode": True,
|
|
1023
|
+
"label_url": ANY,
|
|
1024
|
+
"invoice_url": None,
|
|
1025
|
+
}
|
|
@@ -10,7 +10,7 @@ import rest_framework.pagination as pagination
|
|
|
10
10
|
import rest_framework.throttling as throttling
|
|
11
11
|
import django_filters.rest_framework as django_filters
|
|
12
12
|
|
|
13
|
-
from karrio.server.core.
|
|
13
|
+
from karrio.server.core.utils import validate_resource_token
|
|
14
14
|
import karrio.server.openapi as openapi
|
|
15
15
|
import karrio.server.core.views.api as api
|
|
16
16
|
import karrio.server.core.filters as filters
|
|
@@ -107,26 +107,24 @@ class ManifestDetails(api.APIView):
|
|
|
107
107
|
|
|
108
108
|
class ManifestDoc(django_downloadview.VirtualDownloadView):
|
|
109
109
|
@openapi.extend_schema(exclude=True)
|
|
110
|
-
def get(
|
|
111
|
-
self,
|
|
112
|
-
request: request.Request,
|
|
113
|
-
pk: str,
|
|
114
|
-
doc: str = "manifest",
|
|
115
|
-
format: str = "pdf",
|
|
116
|
-
**kwargs,
|
|
117
|
-
):
|
|
110
|
+
def get(self, req: request.Request, pk: str, doc: str = "manifest", format: str = "pdf", **kwargs):
|
|
118
111
|
"""Retrieve a manifest file."""
|
|
112
|
+
error = validate_resource_token(req, "manifest", [pk], "manifest")
|
|
113
|
+
if error:
|
|
114
|
+
return error
|
|
115
|
+
|
|
116
|
+
query_params = req.GET.dict()
|
|
117
|
+
|
|
119
118
|
self.manifest = models.Manifest.objects.get(pk=pk, manifest__isnull=False)
|
|
120
119
|
self.document = getattr(self.manifest, doc, None)
|
|
121
120
|
self.name = f"{doc}_{self.manifest.id}.{format}"
|
|
122
121
|
|
|
123
|
-
query_params = request.GET.dict()
|
|
124
122
|
self.preview = "preview" in query_params
|
|
125
123
|
self.attachment = "download" in query_params
|
|
126
124
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return
|
|
125
|
+
resp = super(ManifestDoc, self).get(req, pk, doc, format, **kwargs)
|
|
126
|
+
resp["X-Frame-Options"] = "ALLOWALL"
|
|
127
|
+
return resp
|
|
130
128
|
|
|
131
129
|
def get_file(self):
|
|
132
130
|
content = base64.b64decode(self.document or "")
|
|
@@ -14,7 +14,6 @@ import karrio.lib as lib
|
|
|
14
14
|
import karrio.server.openapi as openapi
|
|
15
15
|
import karrio.server.core.filters as filters
|
|
16
16
|
import karrio.server.manager.models as models
|
|
17
|
-
from karrio.server.core.logging import logger
|
|
18
17
|
from karrio.server.core.views.api import GenericAPIView, APIView
|
|
19
18
|
from karrio.server.core.filters import ShipmentFilters
|
|
20
19
|
from karrio.server.manager.router import router
|
|
@@ -267,12 +266,19 @@ class ShipmentDocs(VirtualDownloadView):
|
|
|
267
266
|
format: str = "pdf",
|
|
268
267
|
**kwargs,
|
|
269
268
|
):
|
|
270
|
-
"""Retrieve a shipment label."""
|
|
269
|
+
"""Retrieve a shipment label or invoice."""
|
|
270
|
+
from karrio.server.core.utils import validate_resource_token
|
|
271
|
+
|
|
272
|
+
error = validate_resource_token(request, "shipment", [pk], doc)
|
|
273
|
+
if error:
|
|
274
|
+
return error
|
|
275
|
+
|
|
276
|
+
query_params = request.GET.dict()
|
|
277
|
+
|
|
271
278
|
self.shipment = models.Shipment.objects.get(pk=pk, label__isnull=False)
|
|
272
279
|
self.document = getattr(self.shipment, doc, None)
|
|
273
280
|
self.name = f"{doc}_{self.shipment.tracking_number}.{format}"
|
|
274
281
|
|
|
275
|
-
query_params = request.GET.dict()
|
|
276
282
|
self.preview = "preview" in query_params
|
|
277
283
|
self.attachment = "download" in query_params
|
|
278
284
|
|
{karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/METADATA
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: karrio_server_manager
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.5.1
|
|
4
4
|
Summary: Multi-carrier shipping API Shipments manager module
|
|
5
5
|
Author-email: karrio <hello@karrio.io>
|
|
6
|
-
License-Expression:
|
|
6
|
+
License-Expression: LGPL-3.0
|
|
7
7
|
Project-URL: Homepage, https://github.com/karrioapi/karrio
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Requires-Python: >=3.11
|
{karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/RECORD
RENAMED
|
@@ -82,25 +82,26 @@ karrio/server/manager/serializers/manifest.py,sha256=mSneCk_7HMXpi64_7hggWvkR7Ma
|
|
|
82
82
|
karrio/server/manager/serializers/parcel.py,sha256=733Bg26lVbEkoWtAVM5Qt2IRBS2QDuVxhG40Hiqh3bw,2621
|
|
83
83
|
karrio/server/manager/serializers/pickup.py,sha256=sX0VmcQxGkXn3IEosMuFwdXh4HhdkPcuBOp79O8PoDQ,9233
|
|
84
84
|
karrio/server/manager/serializers/rate.py,sha256=7vYK_v8iWEDnswqYHG2Lir16_UhHTOxW5rdC6lw3lzA,652
|
|
85
|
-
karrio/server/manager/serializers/shipment.py,sha256=
|
|
85
|
+
karrio/server/manager/serializers/shipment.py,sha256=gkDFTDaKXA8Iz3yjS6fxRi46AzZPw40RhJEOlnBZy6o,31143
|
|
86
86
|
karrio/server/manager/serializers/tracking.py,sha256=ixrAjIiZQsvSt4y0qtisGkt6TFOJ3ORNkJAQVt6YQrA,12483
|
|
87
87
|
karrio/server/manager/tests/__init__.py,sha256=Y1UNteEE60vWdUAkjbldu_r_-h4u0He8-UoiBgTjKcU,391
|
|
88
88
|
karrio/server/manager/tests/test_addresses.py,sha256=pNkZC_yJyb29ZlEOtOAs4blcEYiOarw0zhZIZC5uj1w,3111
|
|
89
89
|
karrio/server/manager/tests/test_custom_infos.py,sha256=iv2cLdZVoVWFZK_mDUEnrZssncAnQcn87Rn2sAk8UQI,2731
|
|
90
|
+
karrio/server/manager/tests/test_errors.py,sha256=QYsGLUtwMvrHeX1XSCpdteTKbug7-y1-Xgvbl96aN9g,3220
|
|
90
91
|
karrio/server/manager/tests/test_parcels.py,sha256=lVLBOsHzXgXQvYjHIUy5oiPvrMfxYpueVvvhtuhstWk,2559
|
|
91
92
|
karrio/server/manager/tests/test_pickups.py,sha256=8jxddwTnBvBM9FOyWxW9TtZ-GOVYUje7HQ2EZjsbtD8,10681
|
|
92
|
-
karrio/server/manager/tests/test_shipments.py,sha256=
|
|
93
|
+
karrio/server/manager/tests/test_shipments.py,sha256=N1eVH-n0BTANmzehKL0cp917goskU5X8l_ftXzcVSmw,33349
|
|
93
94
|
karrio/server/manager/tests/test_trackers.py,sha256=KvmWkplokNDZ0dzB16mFl0WcMJ0OYp_ErZeWJPGW_NA,7151
|
|
94
95
|
karrio/server/manager/views/__init__.py,sha256=kDFUaORRQ3Xh0ZPm-Jk88Ss8dgGYM57iUFXb9TPMzh0,401
|
|
95
96
|
karrio/server/manager/views/addresses.py,sha256=7YCAs2ZYgd1icYwMcGGWfX7A7vZEL4BEAbU4eIxhiMY,4620
|
|
96
97
|
karrio/server/manager/views/customs.py,sha256=-ZreiKyJ1xeLeNVG53nMfRQFeURduWr1QkDItdLPnE8,4875
|
|
97
98
|
karrio/server/manager/views/documents.py,sha256=znW54qJ_k7WInIut5FBZFDT93CioozXTOYFKRSUTBhA,4005
|
|
98
|
-
karrio/server/manager/views/manifests.py,sha256=
|
|
99
|
+
karrio/server/manager/views/manifests.py,sha256=_Dd83YxVJOgWhAhD745Kr4tcLWnKaU1dxnT5xB8opvk,5227
|
|
99
100
|
karrio/server/manager/views/parcels.py,sha256=hZY45rg6SrTWfQqyJ38MGKSor1yqgPUEVHtu16aG37g,4594
|
|
100
101
|
karrio/server/manager/views/pickups.py,sha256=gmpxz9ot1OR-BP1qh-0MXU3kUJi1ht_74hfaLJzJ42w,5503
|
|
101
|
-
karrio/server/manager/views/shipments.py,sha256=
|
|
102
|
+
karrio/server/manager/views/shipments.py,sha256=TqLpBH5Jf-rI3enJwvNptRwGzfo7co9R1VSP_oqhB3o,10419
|
|
102
103
|
karrio/server/manager/views/trackers.py,sha256=3oGn2qDpHgk8GZvuz-Cb93Fc0j_h_HbXQR692Zhfiok,12363
|
|
103
|
-
karrio_server_manager-2025.
|
|
104
|
-
karrio_server_manager-2025.
|
|
105
|
-
karrio_server_manager-2025.
|
|
106
|
-
karrio_server_manager-2025.
|
|
104
|
+
karrio_server_manager-2025.5.1.dist-info/METADATA,sha256=7G3zIzLe_6ux6VkjCj1ub1xQc4b9Cz-uiyzwvBpSDDs,730
|
|
105
|
+
karrio_server_manager-2025.5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
106
|
+
karrio_server_manager-2025.5.1.dist-info/top_level.txt,sha256=D1D7x8R3cTfjF_15mfiO7wCQ5QMtuM4x8GaPr7z5i78,12
|
|
107
|
+
karrio_server_manager-2025.5.1.dist-info/RECORD,,
|
{karrio_server_manager-2025.5rc36.dist-info → karrio_server_manager-2025.5.1.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|