refactor: remove redundant free-course check in create_payment_intent#1005
refactor: remove redundant free-course check in create_payment_intent#1005ankushchk wants to merge 1 commit intoalphaonelabs:mainfrom
Conversation
👀 Peer Review RequiredHi @ankushchk! This pull request does not yet have a peer review. Before this PR can be merged, please request a review from one of your peers:
Thank you for contributing! 🎉 |
WalkthroughThe Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/views.py (1)
1608-1616:⚠️ Potential issue | 🟠 MajorMake free-course approval idempotent before sending notifications.
At Line 1609, concurrent/retried requests can both observe
pendingand both trigger Line 1614–Line 1615, causing duplicate side effects. Gate notifications on an atomic status transition.🔧 Proposed fix
enrollment = get_object_or_404(Enrollment, student=request.user, course=course) - if enrollment.status == "pending": - enrollment.status = "approved" - enrollment.save() - - # Send notifications - send_enrollment_confirmation(enrollment) - notify_teacher_new_enrollment(enrollment) + with transaction.atomic(): + status_updated = Enrollment.objects.filter(id=enrollment.id, status="pending").update(status="approved") + + if status_updated: + enrollment.status = "approved" + transaction.on_commit(lambda: send_enrollment_confirmation(enrollment)) + transaction.on_commit(lambda: notify_teacher_new_enrollment(enrollment))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/views.py` around lines 1608 - 1616, The enrollment approval currently checks and sets enrollment.status == "pending" non-atomically, allowing concurrent requests to both pass the check and send duplicate notifications; change the logic to perform an atomic state transition and only send notifications if the transition actually occurred (e.g., use a transactional update or Enrollment.objects.filter(pk=enrollment.pk, status="pending").update(status="approved") and test the affected-row count, or wrap get_object_or_404(Enrollment, ...) in a transaction with select_for_update and update the model), and only call send_enrollment_confirmation(enrollment) and notify_teacher_new_enrollment(enrollment) when the atomic update succeeded; keep references to the Enrollment instance, its status, and the notification functions send_enrollment_confirmation and notify_teacher_new_enrollment to locate and modify the code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@web/views.py`:
- Around line 1608-1616: The enrollment approval currently checks and sets
enrollment.status == "pending" non-atomically, allowing concurrent requests to
both pass the check and send duplicate notifications; change the logic to
perform an atomic state transition and only send notifications if the transition
actually occurred (e.g., use a transactional update or
Enrollment.objects.filter(pk=enrollment.pk,
status="pending").update(status="approved") and test the affected-row count, or
wrap get_object_or_404(Enrollment, ...) in a transaction with select_for_update
and update the model), and only call send_enrollment_confirmation(enrollment)
and notify_teacher_new_enrollment(enrollment) when the atomic update succeeded;
keep references to the Enrollment instance, its status, and the notification
functions send_enrollment_confirmation and notify_teacher_new_enrollment to
locate and modify the code.
Related issues
No existing issue this is a proactive code quality fix discovered during code review.
Description
The
create_payment_intentview inweb/views.pycontained two sequential checks for free/zero-priced courses that were redundant, the second block was unreachable dead code.The problem
The function originally had two back-to-back guards:
Why the second block was dead code:
course.price == 0, the first block returns immediately.price != 0.price <= 0can only beTrueifpriceis negative which is prevented by standard model validation.== 0check wouldn't have caught them, meaning the logic was split unnecessarily.The fix
The PR merges these into a single, more robust guard:
== 0to<= 0now also catches any unexpected negative prices (more defensive).if course.price <= 0block entirely (11 lines of dead code).Checklist
Summary by CodeRabbit