Skip to content

Conversation

@marcoacierno
Copy link
Member

When a user accepts a grant by setting the status to "confirmed", the system now automatically creates a voucher for the free ticket and sends an email to the grantee, similar to how it works for speakers.

Closes #4572

Generated with Claude Code

When a user accepts a grant by setting the status to "confirmed",
the system now automatically creates a voucher for the free ticket
and sends an email to the grantee, similar to how it works for speakers.

Changes:
- Add `create_and_send_grant_voucher` Celery task in grants/tasks.py
  - Creates voucher via Pretix integration
  - Handles case where user already has a speaker voucher (skips)
  - Upgrades co-speaker voucher to grant voucher if applicable
  - Sends voucher code email to the grantee
- Trigger the task when grant status changes to "confirmed" in the
  send_grant_reply GraphQL mutation
- Add tests for the new functionality

Closes #4572

Co-authored-by: Marco Acierno <marcoacierno@users.noreply.github.com>
@vercel
Copy link

vercel bot commented Feb 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pycon Ready Ready Preview Feb 9, 2026 6:49pm

@claude
Copy link
Contributor

claude bot commented Feb 9, 2026

Automatically sends vouchers when grants are confirmed by users. The code correctly delegates to async tasks, handles existing vouchers (including co-speaker upgrades), and follows established patterns for speaker vouchers.

Issues Found

Error Handling

  1. Missing exception handling in create_and_send_grant_voucher (grants/tasks.py:191). The task directly calls external APIs (Pretix via create_conference_voucher) without catching potential failures. If Pretix is unavailable or returns an error, the task will fail silently and the grantee won't receive their voucher. The speaker voucher code in schedule/tasks.py:406 has the same issue, but that doesn't justify repeating it here.

Potential Race Condition

  1. The mutation send_grant_reply (api/grants/mutations.py:336) saves the grant status before triggering the voucher task. If a user rapidly submits multiple replies (or the mutation is called concurrently), the task could be queued multiple times for the same grant. While create_and_send_grant_voucher checks for existing vouchers, there's a window between the check and creation where a race condition could occur. Consider:
    • Using select_for_update() on the grant in the mutation
    • Making the task idempotent by checking grant status at task execution time
    • Using Celery task deduplication

Missing Integration with Admin Flow

  1. The admin action create_grant_vouchers (grants/admin.py:298) creates vouchers but doesn't send emails. When admins bulk-create vouchers for confirmed grants, grantees won't be notified. This creates an inconsistent experience where user-confirmed grants get emails but admin-created vouchers don't. The admin action should call send_conference_voucher_email.delay() after creating vouchers.

Inconsistent Voucher Upgrade Logic

  1. When upgrading a co-speaker voucher to a grant voucher (grants/tasks.py:222), the code only updates the database record but doesn't update the Pretix voucher. The Pretix voucher will still have 25% discount (co-speaker) instead of 100% free (grant). This means the grantee sees a free voucher code in their email, but when they try to use it in Pretix, they only get a 25% discount. The upgrade logic needs to call Pretix API to update the voucher's price_mode and value.

Testing Gap

  1. The test test_create_and_send_grant_voucher_upgrades_co_speaker_voucher (grants/tests/test_tasks.py:74) mocks send_conference_voucher_email but doesn't verify that the Pretix voucher is updated. Without this verification, the production code bug in Conference #4 above wasn't caught.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatically send a voucher for the ticket when a grant is accepted

1 participant