diff --git a/hubspot_xpro/api.py b/hubspot_xpro/api.py index 1311f7c194..1ea5d3ba32 100644 --- a/hubspot_xpro/api.py +++ b/hubspot_xpro/api.py @@ -210,6 +210,17 @@ def sync_contact_hubspot_ids_to_db(): alt_email_q |= Q(email__iexact=alt_email) user = User.objects.filter(alt_email_q).first() if user: + # Skip if this hubspot_id is already mapped to a different user + existing = ( + HubspotObject.objects.filter( + content_type=content_type, + hubspot_id=contact.id, + ) + .exclude(object_id=user.id) + .exists() + ) + if existing: + continue HubspotObject.objects.update_or_create( content_type=content_type, object_id=user.id, @@ -332,6 +343,8 @@ def sync_deal_line_hubspot_ids_to_db(order, hubspot_order_id) -> bool: matches = 0 expected_matches = 1 if is_b2b else order.lines.count() + if not line_items: + return False if is_b2b or len(line_items) == 1: HubspotObject.objects.update_or_create( content_type=ContentType.objects.get_for_model(order_line), diff --git a/hubspot_xpro/tasks.py b/hubspot_xpro/tasks.py index 8ba716c619..35930b6ecf 100644 --- a/hubspot_xpro/tasks.py +++ b/hubspot_xpro/tasks.py @@ -378,9 +378,16 @@ def batch_create_hubspot_objects_chunked( errored_chunks.append(still_failed) time.sleep(settings.HUBSPOT_TASK_DELAY / 1000) if errored_chunks: - raise ApiException( - status=last_error_status, - reason=f"Batch hubspot create failed for the following chunks: {errored_chunks}", + if last_error_status == 429: # noqa: PLR2004 + raise ApiException( + status=last_error_status, + reason=f"Batch hubspot create failed for the following chunks: {errored_chunks}", + ) + log.error( + "Batch hubspot create failed for type %s, chunks: %s (status %s)", + hubspot_type, + errored_chunks, + last_error_status, ) return created_ids diff --git a/hubspot_xpro/tasks_test.py b/hubspot_xpro/tasks_test.py index a28847e5bc..171eb2e012 100644 --- a/hubspot_xpro/tasks_test.py +++ b/hubspot_xpro/tasks_test.py @@ -301,7 +301,7 @@ def test_batch_create_hubspot_objects_chunked(mocker, id_count): @pytest.mark.parametrize( "status, expected_error", # noqa: PT006 - [[429, TooManyRequestsException], [500, ApiException]], # noqa: PT007 + [[429, TooManyRequestsException], [500, None]], # noqa: PT007 ) def test_batch_create_hubspot_objects_chunked_error(mocker, status, expected_error): """batch_create_hubspot_objects_chunked raise expected exception""" @@ -314,12 +314,20 @@ def test_batch_create_hubspot_objects_chunked_error(mocker, status, expected_err side_effect=(ApiException(status=status)), ) chunk = sorted([user.id for user in UserFactory.create_batch(3)]) - with pytest.raises(expected_error): - tasks.batch_create_hubspot_objects_chunked( + if expected_error: + with pytest.raises(expected_error): + tasks.batch_create_hubspot_objects_chunked( + HubspotObjectType.CONTACTS.value, + "user", + chunk, + ) + else: + result = tasks.batch_create_hubspot_objects_chunked( HubspotObjectType.CONTACTS.value, "user", chunk, ) + assert result == [] for item in chunk: mock_sync_contact.assert_any_call(item)