Add ticket +/- quantity support to shared contracts and services
- Add ticket_type_id field to TicketDTO for grouping - Add adjust_ticket_quantity to CalendarService protocol + SQL impl - Add stub for adjust_ticket_quantity Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -56,6 +56,7 @@ class TicketDTO:
|
|||||||
created_at: datetime | None = None
|
created_at: datetime | None = None
|
||||||
checked_in_at: datetime | None = None
|
checked_in_at: datetime | None = None
|
||||||
entry_id: int | None = None
|
entry_id: int | None = None
|
||||||
|
ticket_type_id: int | None = None
|
||||||
price: Decimal | None = None
|
price: Decimal | None = None
|
||||||
order_id: int | None = None
|
order_id: int | None = None
|
||||||
calendar_container_id: int | None = None
|
calendar_container_id: int | None = None
|
||||||
|
|||||||
@@ -112,6 +112,12 @@ class CalendarService(Protocol):
|
|||||||
self, session: AsyncSession, user_id: int, session_id: str,
|
self, session: AsyncSession, user_id: int, session_id: str,
|
||||||
) -> None: ...
|
) -> None: ...
|
||||||
|
|
||||||
|
async def adjust_ticket_quantity(
|
||||||
|
self, session: AsyncSession, entry_id: int, count: int, *,
|
||||||
|
user_id: int | None, session_id: str | None,
|
||||||
|
ticket_type_id: int | None = None,
|
||||||
|
) -> int: ...
|
||||||
|
|
||||||
async def entry_ids_for_content(
|
async def entry_ids_for_content(
|
||||||
self, session: AsyncSession, content_type: str, content_id: int,
|
self, session: AsyncSession, content_type: str, content_id: int,
|
||||||
) -> set[int]: ...
|
) -> set[int]: ...
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ def _ticket_to_dto(ticket: Ticket) -> TicketDTO:
|
|||||||
created_at=ticket.created_at,
|
created_at=ticket.created_at,
|
||||||
checked_in_at=ticket.checked_in_at,
|
checked_in_at=ticket.checked_in_at,
|
||||||
entry_id=entry.id if entry else None,
|
entry_id=entry.id if entry else None,
|
||||||
|
ticket_type_id=ticket.ticket_type_id,
|
||||||
price=price,
|
price=price,
|
||||||
order_id=ticket.order_id,
|
order_id=ticket.order_id,
|
||||||
calendar_container_id=cal.container_id if cal else None,
|
calendar_container_id=cal.container_id if cal else None,
|
||||||
@@ -563,3 +564,59 @@ class SqlCalendarService:
|
|||||||
)
|
)
|
||||||
for ticket in result.scalars().all():
|
for ticket in result.scalars().all():
|
||||||
ticket.user_id = user_id
|
ticket.user_id = user_id
|
||||||
|
|
||||||
|
async def adjust_ticket_quantity(
|
||||||
|
self, session: AsyncSession, entry_id: int, count: int, *,
|
||||||
|
user_id: int | None, session_id: str | None,
|
||||||
|
ticket_type_id: int | None = None,
|
||||||
|
) -> int:
|
||||||
|
"""Adjust reserved ticket count to target. Returns new count."""
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
count = max(count, 0)
|
||||||
|
|
||||||
|
# Current reserved count
|
||||||
|
filters = [
|
||||||
|
Ticket.entry_id == entry_id,
|
||||||
|
Ticket.state == "reserved",
|
||||||
|
]
|
||||||
|
if user_id is not None:
|
||||||
|
filters.append(Ticket.user_id == user_id)
|
||||||
|
elif session_id is not None:
|
||||||
|
filters.append(Ticket.session_id == session_id)
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
if ticket_type_id is not None:
|
||||||
|
filters.append(Ticket.ticket_type_id == ticket_type_id)
|
||||||
|
|
||||||
|
current = await session.scalar(
|
||||||
|
select(func.count(Ticket.id)).where(*filters)
|
||||||
|
) or 0
|
||||||
|
|
||||||
|
if count > current:
|
||||||
|
# Create tickets
|
||||||
|
for _ in range(count - current):
|
||||||
|
ticket = Ticket(
|
||||||
|
entry_id=entry_id,
|
||||||
|
ticket_type_id=ticket_type_id,
|
||||||
|
user_id=user_id,
|
||||||
|
session_id=session_id,
|
||||||
|
code=uuid.uuid4().hex,
|
||||||
|
state="reserved",
|
||||||
|
)
|
||||||
|
session.add(ticket)
|
||||||
|
await session.flush()
|
||||||
|
elif count < current:
|
||||||
|
# Cancel newest tickets
|
||||||
|
to_cancel = current - count
|
||||||
|
result = await session.execute(
|
||||||
|
select(Ticket)
|
||||||
|
.where(*filters)
|
||||||
|
.order_by(Ticket.created_at.desc())
|
||||||
|
.limit(to_cancel)
|
||||||
|
)
|
||||||
|
for ticket in result.scalars().all():
|
||||||
|
ticket.state = "cancelled"
|
||||||
|
await session.flush()
|
||||||
|
|
||||||
|
return count
|
||||||
|
|||||||
@@ -132,6 +132,11 @@ class StubCalendarService:
|
|||||||
) -> None:
|
) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
async def adjust_ticket_quantity(
|
||||||
|
self, session, entry_id, count, *, user_id, session_id, ticket_type_id=None,
|
||||||
|
) -> int:
|
||||||
|
return 0
|
||||||
|
|
||||||
async def entry_ids_for_content(self, session, content_type, content_id):
|
async def entry_ids_for_content(self, session, content_type, content_id):
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user