FIX(promotions): resolve user UUID before saving application events

ApplicationEventViewSet.perform_create() was passing the full request.user
model instance into Event.user (a plain UUIDField), which raises on every
real call. Use the same _resolve_user() -> user.uuid pattern already used by
status(), and raise UnprocessableEntity on save_event failure to match the
v1 endpoint's error-handling convention.
This commit is contained in:
Ali Asadi 2026-08-18 14:26:14 +03:30
parent 1a63acee32
commit 1536016f14
2 changed files with 43 additions and 6 deletions

View file

@ -720,6 +720,46 @@ class ApplicationApiFlowsTests(APITestCase):
print(response.json())
self.assertEqual(response.status_code, 404)
def test_application_event_viewset_create_success(self):
EventSaver.objects.get_or_create(
title=self.first_ad_view_reward_label,
event_label=self.first_ad_view_reward_label,
save_once=False,
)
auth = self._create_authorization_header(self.application_access_token.token)
event_create_data = {
'label': self.first_ad_view_reward_label,
'data': {'foo': 'bar'},
}
url = reverse('promotions-application:event-list', kwargs={'user_uuid': str(self.user_1_uuid)})
response = self.client.post(url, event_create_data, HTTP_AUTHORIZATION=auth, format='json')
self.assertEqual(response.status_code, 201)
event = Event.objects.get(label=self.first_ad_view_reward_label)
self.assertEqual(event.user, self.user_1_uuid)
def test_application_event_viewset_create_duplicate_returns_unprocessable_entity(self):
EventSaver.objects.get_or_create(
title=self.first_ad_view_reward_label,
event_label=self.first_ad_view_reward_label,
save_once=True,
)
auth = self._create_authorization_header(self.application_access_token.token)
event_create_data = {
'label': self.first_ad_view_reward_label,
'data': {'foo': 'bar'},
}
url = reverse('promotions-application:event-list', kwargs={'user_uuid': str(self.user_1_uuid)})
first_response = self.client.post(url, event_create_data, HTTP_AUTHORIZATION=auth, format='json')
self.assertEqual(first_response.status_code, 201)
second_response = self.client.post(url, event_create_data, HTTP_AUTHORIZATION=auth, format='json')
self.assertEqual(second_response.status_code, 422)
def _create_first_ad_create_plan(self):
event_label = 'ads::first-ad-create'
plan_title = 'first-ad-create'

View file

@ -145,18 +145,15 @@ class ApplicationEventViewSet(
return Response(serializer.data)
def perform_create(self, serializer: EventSerializer):
if hasattr(self.request, 'user'):
user = self.request.user
else:
user = None
user = self._resolve_user()
application = get_application(self.request)
# EventSaver.objects.first(event_label=serializer.validated_data['event_label'], valid_application__contains=application.uuid)
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
try:
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
event = event_saver.save_event(user=user.uuid, application=application, **serializer.validated_data)
except Exception as e:
raise exceptions.ValidationError(str(e))
raise UnprocessableEntity(str(e))
analyze_event_task.delay(event.uuid)
serializer.instance = event