diff --git a/modules/core/karrio/server/core/serializers.py b/modules/core/karrio/server/core/serializers.py index faf9fd2cca..53c0a517f1 100644 --- a/modules/core/karrio/server/core/serializers.py +++ b/modules/core/karrio/server/core/serializers.py @@ -861,6 +861,15 @@ class TrackingData(serializers.Serializer): required=True, help_text="The tracking carrier", ) + carrier_id = serializers.CharField( + required=False, + allow_blank=False, + allow_null=True, + help_text=( + "Optional carrier connection identifier (connection id or carrier_id). " + "Useful when multiple connections exist for the same carrier." + ), + ) account_number = serializers.CharField( required=False, allow_blank=True, diff --git a/modules/manager/karrio/server/manager/serializers/tracking.py b/modules/manager/karrio/server/manager/serializers/tracking.py index f48bbc40f3..ff61a2b1c9 100644 --- a/modules/manager/karrio/server/manager/serializers/tracking.py +++ b/modules/manager/karrio/server/manager/serializers/tracking.py @@ -47,7 +47,14 @@ class TrackingSerializer(TrackingDetails): def create(self, validated_data: dict, context, **kwargs) -> models.Tracking: options = validated_data["options"] metadata = validated_data["metadata"] - carrier_filter = validated_data["carrier_filter"] + carrier_filter = { + **validated_data["carrier_filter"], + **( + {"carrier_id": validated_data["carrier_id"]} + if validated_data.get("carrier_id") + else {} + ), + } tracking_number = validated_data["tracking_number"] account_number = validated_data.get("account_number") info = validated_data.get("info") diff --git a/modules/manager/karrio/server/manager/tests/test_trackers.py b/modules/manager/karrio/server/manager/tests/test_trackers.py index 0f897a4321..65870d56cd 100644 --- a/modules/manager/karrio/server/manager/tests/test_trackers.py +++ b/modules/manager/karrio/server/manager/tests/test_trackers.py @@ -44,6 +44,33 @@ def test_shipment_tracking_retry(self): self.assertDictEqual(response_data, TRACKING_RESPONSE) self.assertEqual(len(self.user.tracking_set.all()), 1) + def test_create_tracker_with_carrier_id(self): + url = reverse("karrio.server.manager:trackers-list") + data = dict( + tracking_number="1Z12345E6205277936", + carrier_name="ups", + carrier_id="ups_domestic", + ) + + with patch( + "karrio.server.manager.serializers.tracking.Connections.first" + ) as connection_mock, patch("karrio.server.core.gateway.utils.identity") as mock: + connection_mock.return_value = self.ups_carrier + mock.return_value = RETURNED_VALUE + + response = self.client.post(url, data) + + self.assertResponseNoErrors(response) + self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED) + connection_mock.assert_called_once_with( + context=ANY, + raise_not_found=True, + active=True, + capability="tracking", + carrier_name="ups", + carrier_id="ups_domestic", + ) + class TestTrackersUpdate(APITestCase): def setUp(self) -> None: diff --git a/modules/proxy/karrio/server/proxy/tests/test_tracking.py b/modules/proxy/karrio/server/proxy/tests/test_tracking.py index ac3ce4c2ea..edad6ad053 100644 --- a/modules/proxy/karrio/server/proxy/tests/test_tracking.py +++ b/modules/proxy/karrio/server/proxy/tests/test_tracking.py @@ -3,10 +3,17 @@ from django.urls import reverse from rest_framework import status from karrio.core.models import TrackingDetails, TrackingEvent +from karrio.server.core.serializers import TrackingData from karrio.server.core.tests import APITestCase class TestTracking(APITestCase): + def test_tracking_data_accepts_carrier_id_without_test_mode_body_field(self): + fields = TrackingData().fields + + self.assertIn("carrier_id", fields) + self.assertNotIn("test_mode", fields) + def test_tracking_shipment(self): url = reverse("karrio.server.proxy:get-tracking") data = dict(tracking_number="1Z12345E6205277936", carrier_name="ups") @@ -19,6 +26,32 @@ def test_tracking_shipment(self): self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertDictEqual(response_data, TRACKING_RESPONSE) + def test_tracking_shipment_with_carrier_id(self): + url = reverse("karrio.server.proxy:get-tracking") + data = dict( + tracking_number="1Z12345E6205277936", + carrier_name="ups", + carrier_id="ups_domestic", + ) + + with patch("karrio.server.core.gateway.Carriers.first") as carrier_mock, patch( + "karrio.server.core.gateway.utils.identity" + ) as mock: + carrier_mock.return_value = self.ups_carrier + mock.return_value = RETURNED_VALUE + + response = self.client.post(url, data) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + carrier_mock.assert_called_once_with( + active=True, + capability="tracking", + raise_not_found=True, + context=ANY, + carrier_name="ups", + carrier_id="ups_domestic", + ) + RETURNED_VALUE = [ [ diff --git a/modules/proxy/karrio/server/proxy/views/tracking.py b/modules/proxy/karrio/server/proxy/views/tracking.py index 44a2e2f9de..2fbdccd6ac 100644 --- a/modules/proxy/karrio/server/proxy/views/tracking.py +++ b/modules/proxy/karrio/server/proxy/views/tracking.py @@ -57,6 +57,8 @@ def post(self, request: Request): query.get("hub") if "hub" in query else data["carrier_name"] ), } + if data.get("carrier_id"): + carrier_filter["carrier_id"] = data["carrier_id"] data = { **data, "tracking_numbers": [data["tracking_number"]],