Compare commits
base: aiolabs:c8602e0fbd016614196b29842f3cc1430be4573b
aiolabs:main
aiolabs:feat/organizer-sender-identity
aiolabs:feat/ticket-email-sent-copy
aiolabs:ticket-scanner-nostr
aiolabs:backup/main-pre-v1.3-rebase-2026-05-05
aiolabs:feat/event-approval-workflow
aiolabs:fix/sqlite-ticket-extra-serialization
aiolabs:v1.6.8-aio.4
aiolabs:v1.6.8-aio.3
aiolabs:v1.6.8-aio.2
aiolabs:v1.6.8-aio.1
aiolabs:v1.6.1-aio.18
aiolabs:v1.6.1-aio.17
aiolabs:v1.6.1-aio.16
aiolabs:v1.6.1-aio.15
aiolabs:v1.6.1-aio.14
aiolabs:v1.6.1-aio.13
aiolabs:v1.6.1-aio.10
aiolabs:v1.6.1-aio.9
aiolabs:v1.6.1-aio.8
aiolabs:v1.6.1-aio.6
aiolabs:v1.6.1-aio.5
aiolabs:v1.6.1-aio.3
aiolabs:v1.6.1-aio.2
aiolabs:v1.6.1-aio.1
aiolabs:v1.3.0-aio.6
aiolabs:v1.3.0-aio.5
aiolabs:v1.3.0-aio.4
aiolabs:v1.3.0-aio.3
aiolabs:v1.3.0-aio.2
aiolabs:v1.3.0-aio.1
aiolabs:v1.2.1-aio.2
aiolabs:v1.2.1-aio.1
aiolabs:v1.2.1
aiolabs:v0.0.2
aiolabs:v0.0.1
aiolabs:v1.2.0
aiolabs:v1.1.0
aiolabs:v1.0.0
aiolabs:v0.2.0
aiolabs:v0.1.6
aiolabs:v0.1.5
aiolabs:v0.1.4
aiolabs:v0.1.3
aiolabs:0.1.2
aiolabs:0.1.1
aiolabs:0.1
..
compare: aiolabs:7b761a1aef739b83ec336a1e5fe8a0c850402689
aiolabs:main
aiolabs:feat/organizer-sender-identity
aiolabs:feat/ticket-email-sent-copy
aiolabs:ticket-scanner-nostr
aiolabs:backup/main-pre-v1.3-rebase-2026-05-05
aiolabs:feat/event-approval-workflow
aiolabs:fix/sqlite-ticket-extra-serialization
aiolabs:v1.6.8-aio.4
aiolabs:v1.6.8-aio.3
aiolabs:v1.6.8-aio.2
aiolabs:v1.6.8-aio.1
aiolabs:v1.6.1-aio.18
aiolabs:v1.6.1-aio.17
aiolabs:v1.6.1-aio.16
aiolabs:v1.6.1-aio.15
aiolabs:v1.6.1-aio.14
aiolabs:v1.6.1-aio.13
aiolabs:v1.6.1-aio.10
aiolabs:v1.6.1-aio.9
aiolabs:v1.6.1-aio.8
aiolabs:v1.6.1-aio.6
aiolabs:v1.6.1-aio.5
aiolabs:v1.6.1-aio.3
aiolabs:v1.6.1-aio.2
aiolabs:v1.6.1-aio.1
aiolabs:v1.3.0-aio.6
aiolabs:v1.3.0-aio.5
aiolabs:v1.3.0-aio.4
aiolabs:v1.3.0-aio.3
aiolabs:v1.3.0-aio.2
aiolabs:v1.3.0-aio.1
aiolabs:v1.2.1-aio.2
aiolabs:v1.2.1-aio.1
aiolabs:v1.2.1
aiolabs:v0.0.2
aiolabs:v0.0.1
aiolabs:v1.2.0
aiolabs:v1.1.0
aiolabs:v1.0.0
aiolabs:v0.2.0
aiolabs:v0.1.6
aiolabs:v0.1.5
aiolabs:v0.1.4
aiolabs:v0.1.3
aiolabs:0.1.2
aiolabs:0.1.1
aiolabs:0.1
2 commits
c8602e0fbd
...
7b761a1aef
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
| 7b761a1aef |
fix: every ticket row gets a fresh short-hash id (no payment_hash reuse)
Previous commit reused the LNbits invoice payment_hash as the first row's id, so a 3-ticket purchase ended up with one 64-hex id and two short-hash ids — inconsistent and noisy in My Tickets. Switch every row to urlsafe_short_hash. The shared payment_hash column is the join key for invoice lookups (poll endpoint, ws notifier, on_invoice_paid); rows never need to BE the payment hash, they only need to point at it. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
|||
| 59068fe09d |
feat: multi-ticket purchases as N rows sharing one payment_hash
Replaces the previous "one row, N seats via extra.quantity" model
with proper one-row-per-attendee semantics. Each attendee gets a
unique scannable id; the door PUT /register/{ticket_id} marks
them registered independently — so a buyer can purchase 3 tickets,
hand 2 QRs to friends arriving separately, and each attendee can
enter on their own schedule.
Schema (migrations_fork.py m002):
- ticket.payment_hash: new TEXT column shared across all rows of
a multi-ticket purchase. Backfilled `payment_hash = id` for
pre-migration rows (id WAS the payment_hash by invariant).
Wire:
- TicketPaymentRequest grows `ticket_ids: list[str]` so the
webapp gets every scannable id back in the create response.
- POST /tickets/{event_id}/{payment_hash} polling endpoint now
reports `ticket_ids` (every row) + keeps `ticket_id` for
back-compat.
- api_ticket_create loops quantity times; the first row reuses
payment_hash as id (preserves legacy `id == payment_hash`
invariant for single-ticket purchases), the rest get
urlsafe_short_hash() uuids.
Payment flow:
- on_invoice_paid fetches all rows by payment_hash and marks each
paid via set_ticket_paid, which now increments event.sold by 1
per row (was N per row via extra.quantity — simpler now). The
per-event asyncio lock still serializes counter + republish so
concurrent multi-ticket purchases for the same event don't
reorder the published Nostr state.
- Each paid row triggers its own send_ticket_notification_in_
background call — no-op for buyers without nostr_identifier /
email, useful when the buyer set those on the row.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|