Compare commits
No commits in common. "26c0a5c4295ab26204a281a67ac8a59cb0c71800" and "e706b46003eaaac30d1fb1df9262ae777f272672" have entirely different histories.
26c0a5c429
...
e706b46003
2 changed files with 7 additions and 79 deletions
22
models.py
22
models.py
|
|
@ -58,8 +58,7 @@ class TicketWave(BaseModel):
|
|||
|
||||
|
||||
class EventExtraBase(BaseModel):
|
||||
"""Everything in `extra` that is safe to show anyone — ticket waves
|
||||
included, since a buyer needs a wave id to choose one. `EventExtra` adds
|
||||
"""Everything in `extra` that is safe to show anyone. `EventExtra` adds
|
||||
the organizer-only promo codes on top; `PublicEventExtra` is this base,
|
||||
so anonymous responses can never carry them."""
|
||||
|
||||
|
|
@ -74,19 +73,6 @@ class EventExtraBase(BaseModel):
|
|||
# `effective_payment_methods`. Same field name/shape as upstream v2 so the
|
||||
# eventual rebase (#33) merges cleanly.
|
||||
payment_methods: list[str] = Field(default_factory=list)
|
||||
# Upstream v1.6.8 ticket waves — time-boxed pricing tiers. The
|
||||
# event-level `currency` / `allow_fiat` / `amount_tickets` /
|
||||
# `price_per_ticket` fields become derived values (see
|
||||
# `sync_event_ticket_waves`), which is why fork code that reads them
|
||||
# needs auditing — aiolabs/events#61.
|
||||
#
|
||||
# Public, not organizer-only: a buyer cannot choose a wave without its
|
||||
# id, and neither the public event response nor the NIP-52 tags carried
|
||||
# one before. A wave holds price, dates and remaining stock — the sales
|
||||
# information a buyer needs — so the only thing exposing it reveals is
|
||||
# the upcoming price schedule, which is what #61 regretted giving up
|
||||
# when it settled on flat Nostr tags.
|
||||
ticket_waves: list[TicketWave] = Field(default_factory=list)
|
||||
|
||||
@validator("payment_methods", pre=True)
|
||||
def normalize_payment_methods(cls, v):
|
||||
|
|
@ -106,6 +92,12 @@ class EventExtraBase(BaseModel):
|
|||
|
||||
class EventExtra(EventExtraBase):
|
||||
promo_codes: list[PromoCode] = Field(default_factory=list)
|
||||
# Upstream v1.6.8 ticket waves — time-boxed pricing tiers. The
|
||||
# event-level `currency` / `allow_fiat` / `amount_tickets` /
|
||||
# `price_per_ticket` fields become derived values (see
|
||||
# `sync_event_ticket_waves`), which is why fork code that reads them
|
||||
# needs auditing — aiolabs/events#61.
|
||||
ticket_waves: list[TicketWave] = Field(default_factory=list)
|
||||
|
||||
|
||||
PublicEventExtra = EventExtraBase
|
||||
|
|
|
|||
|
|
@ -5,10 +5,6 @@ from ..models import (
|
|||
CreateEvent,
|
||||
CreateTicket,
|
||||
EventExtra,
|
||||
PromoCode,
|
||||
PublicEvent,
|
||||
PublicEventExtra,
|
||||
TicketWave,
|
||||
effective_payment_methods,
|
||||
)
|
||||
|
||||
|
|
@ -112,63 +108,3 @@ def test_payment_methods_are_normalised_and_deduplicated():
|
|||
def test_unknown_payment_method_is_rejected():
|
||||
with pytest.raises(ValidationError):
|
||||
EventExtra(payment_methods=["cash"])
|
||||
|
||||
|
||||
# --- public projection ------------------------------------------------------
|
||||
|
||||
|
||||
def test_public_extra_exposes_waves_but_never_promo_codes():
|
||||
"""A buyer needs a wave id to choose a tier, so waves are public; promo
|
||||
codes stay organizer-only (aiolabs/events#61, v1.6.1-aio.12)."""
|
||||
organizer = EventExtra(
|
||||
promo_codes=[PromoCode(code="SECRET", discount_percent=50)],
|
||||
ticket_waves=[
|
||||
TicketWave(
|
||||
id="early",
|
||||
title="Early",
|
||||
opening_date="2030-01-01",
|
||||
closing_date="2030-02-01",
|
||||
currency="sat",
|
||||
price_per_ticket=10,
|
||||
amount_tickets=5,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
public = PublicEventExtra(**organizer.dict())
|
||||
|
||||
assert [wave.id for wave in public.ticket_waves] == ["early"]
|
||||
assert public.ticket_waves[0].price_per_ticket == 10
|
||||
assert not hasattr(public, "promo_codes")
|
||||
assert "promo_codes" not in public.dict()
|
||||
|
||||
|
||||
def test_public_event_response_carries_waves():
|
||||
"""End of the chain: what `GET /events/{id}` actually serialises."""
|
||||
wave = TicketWave(
|
||||
id="regular",
|
||||
title="Regular",
|
||||
opening_date="2030-01-01",
|
||||
closing_date="2030-02-01",
|
||||
currency="sat",
|
||||
price_per_ticket=25,
|
||||
amount_tickets=40,
|
||||
)
|
||||
organizer_extra = EventExtra(
|
||||
ticket_waves=[wave], promo_codes=[PromoCode(code="SECRET")]
|
||||
)
|
||||
public = PublicEvent(
|
||||
id="evt",
|
||||
name="Test",
|
||||
info="",
|
||||
canceled=False,
|
||||
event_start_date="2030-01-01",
|
||||
currency="sat",
|
||||
price_per_ticket=25,
|
||||
banner=None,
|
||||
extra=PublicEventExtra(**organizer_extra.dict()),
|
||||
)
|
||||
body = public.dict()
|
||||
|
||||
assert [w["id"] for w in body["extra"]["ticket_waves"]] == ["regular"]
|
||||
assert "promo_codes" not in body["extra"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue