From c8b31d8e3f5dc73e83c62d6207f8c446ea9ffa28 Mon Sep 17 00:00:00 2001 From: Tiago Vasconcelos Date: Fri, 18 Aug 2023 07:17:29 +0100 Subject: [PATCH 01/64] [FEAT] add timestamp on register (#15) * add timestamp on register --- README.md | 1 + config.json | 8 ++++---- crud.py | 3 ++- manifest.json | 14 +++++++------- migrations.py | 11 +++++++++-- models.py | 2 ++ views_api.py | 9 ++++++++- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c55b8b2..ebd7194 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Events - [LNbits](https://github.com/lnbits/lnbits) extension + For more about LNBits extension check [this tutorial](https://github.com/lnbits/lnbits/wiki/LNbits-Extensions) ## Sell tickets for events and use the built-in scanner for registering attendants diff --git a/config.json b/config.json index a62bcc4..bdc8ba6 100644 --- a/config.json +++ b/config.json @@ -1,6 +1,6 @@ { - "name": "Events", - "short_description": "Sell and register event tickets", - "tile": "/events/static/image/events.png", - "contributors": ["benarc"] + "name": "Events", + "short_description": "Sell and register event tickets", + "tile": "/events/static/image/events.png", + "contributors": ["benarc"] } diff --git a/crud.py b/crud.py index fc3de9d..00c7b72 100644 --- a/crud.py +++ b/crud.py @@ -135,7 +135,8 @@ async def get_event_tickets(event_id: str, wallet_id: str) -> List[Ticket]: async def reg_ticket(ticket_id: str) -> List[Ticket]: await db.execute( - "UPDATE events.ticket SET registered = ? WHERE id = ?", (True, ticket_id) + f"UPDATE events.ticket SET registered = ?, reg_timestamp = {db.timestamp_now} WHERE id = ?", + (True, ticket_id), ) ticket = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (ticket_id,)) rows = await db.fetchall( diff --git a/manifest.json b/manifest.json index 13726a7..cee435b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { - "repos": [ - { - "id": "events", - "organisation": "lnbits", - "repository": "events" - } - ] + "repos": [ + { + "id": "events", + "organisation": "lnbits", + "repository": "events" + } + ] } diff --git a/migrations.py b/migrations.py index 5b9d53b..77424eb 100644 --- a/migrations.py +++ b/migrations.py @@ -1,5 +1,4 @@ async def m001_initial(db): - await db.execute( """ CREATE TABLE events.events ( @@ -38,7 +37,6 @@ async def m001_initial(db): async def m002_changed(db): - await db.execute( """ CREATE TABLE events.ticket ( @@ -81,3 +79,12 @@ async def m002_changed(db): (row[0], row[1], row[2], row[3], row[4], row[5], True), ) await db.execute("DROP TABLE events.tickets") + + +async def m003_add_register_timestamp(db): + """ + Add a column to register the timestamp of ticket register + """ + await db.execute( + "ALTER TABLE events.ticket ADD COLUMN reg_timestamp TIMESTAMP;" + ) # NULL means not registered, or old ticket diff --git a/models.py b/models.py index b9bf7c0..62cba60 100644 --- a/models.py +++ b/models.py @@ -1,5 +1,6 @@ from fastapi import Query from pydantic import BaseModel +from typing import Optional class CreateEvent(BaseModel): @@ -39,5 +40,6 @@ class Ticket(BaseModel): name: str email: str registered: bool + reg_timestamp: Optional[int] paid: bool time: int diff --git a/views_api.py b/views_api.py index c0d9809..de53202 100644 --- a/views_api.py +++ b/views_api.py @@ -109,7 +109,13 @@ async def api_ticket_make_ticket(event_id, name, email): memo=f"{event_id}", extra={"tag": "events", "name": name, "email": email}, ) - await create_ticket(payment_hash=payment_hash, wallet=event.wallet, event=event.id, name=name, email=email) + await create_ticket( + payment_hash=payment_hash, + wallet=event.wallet, + event=event.id, + name=name, + email=email, + ) except Exception as e: raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR, detail=str(e)) return {"payment_hash": payment_hash, "payment_request": payment_request} @@ -167,6 +173,7 @@ async def api_event_tickets(wallet_id, event_id): @events_ext.get("/api/v1/register/ticket/{ticket_id}") async def api_event_register_ticket(ticket_id): ticket = await get_ticket(ticket_id) + if not ticket: raise HTTPException( status_code=HTTPStatus.NOT_FOUND, detail="Ticket does not exist." From 00f552c7510eef5cd7e5cb13bb87af3914029bfd Mon Sep 17 00:00:00 2001 From: Tiago Vasconcelos Date: Fri, 18 Aug 2023 07:18:44 +0100 Subject: [PATCH 02/64] Fix ticket create (#13) * don't set ticket as paid on create * use crud fn in tasks.py * create ticket is unpaid by default --- crud.py | 52 +++++++++++++++++++++++------------ tasks.py | 9 ++---- templates/events/display.html | 1 - views_api.py | 3 ++ 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/crud.py b/crud.py index 00c7b72..f347936 100644 --- a/crud.py +++ b/crud.py @@ -9,34 +9,52 @@ from .models import CreateEvent, Event, Ticket async def create_ticket( - payment_hash: str, wallet: str, event: str, name: str, email: str -) -> Ticket: + payment_hash: str, wallet: str, event: str, name: str, email: str) -> Ticket: await db.execute( """ INSERT INTO events.ticket (id, wallet, event, name, email, registered, paid) VALUES (?, ?, ?, ?, ?, ?, ?) """, - (payment_hash, wallet, event, name, email, False, True), - ) - - # UPDATE EVENT DATA ON SOLD TICKET - eventdata = await get_event(event) - assert eventdata, "Couldn't get event from ticket being paid" - sold = eventdata.sold + 1 - amount_tickets = eventdata.amount_tickets - 1 - await db.execute( - """ - UPDATE events.events - SET sold = ?, amount_tickets = ? - WHERE id = ? - """, - (sold, amount_tickets, event), + (payment_hash, wallet, event, name, email, False, False), ) ticket = await get_ticket(payment_hash) assert ticket, "Newly created ticket couldn't be retrieved" return ticket +async def set_ticket_paid(payment_hash: str) -> Ticket: + ticket = await get_ticket(payment_hash) + assert ticket, "Ticket couldn't be retrieved" + + await db.execute( + """ + UPDATE events.ticket + SET paid = ? + WHERE id = ? + """, + (True, ticket.id), + ) + + await update_event_sold(ticket.event) + + return ticket + +async def update_event_sold(event_id: str): + event = await get_event(event_id) + assert event, "Couldn't get event from ticket being paid" + sold = event.sold + 1 + amount_tickets = event.amount_tickets - 1 + await db.execute( + """ + UPDATE events.events + SET sold = ?, amount_tickets = ? + WHERE id = ? + """, + (sold, amount_tickets, event_id), + ) + + return + async def get_ticket(payment_hash: str) -> Optional[Ticket]: row = await db.fetchone("SELECT * FROM events.ticket WHERE id = ?", (payment_hash,)) diff --git a/tasks.py b/tasks.py index 68a3908..d2ed732 100644 --- a/tasks.py +++ b/tasks.py @@ -4,8 +4,7 @@ from lnbits.core.models import Payment from lnbits.helpers import get_current_extension_name from lnbits.tasks import register_invoice_listener -from .models import CreateTicket -from .views_api import api_ticket_send_ticket +from .crud import set_ticket_paid async def wait_for_paid_invoices(): @@ -25,8 +24,6 @@ async def on_invoice_paid(payment: Payment) -> None: and payment.extra.get("name") and payment.extra.get("email") ): - await api_ticket_send_ticket( - payment.memo, - payment.payment_hash, - ) + + await set_ticket_paid(payment.payment_hash) return diff --git a/templates/events/display.html b/templates/events/display.html index 45c2aca..74fd871 100644 --- a/templates/events/display.html +++ b/templates/events/display.html @@ -86,7 +86,6 @@ {% endblock %} {% block scripts %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/events/index.html b/templates/events/index.html index 57afb19..9bd1e4c 100644 --- a/templates/events/index.html +++ b/templates/events/index.html @@ -4,9 +4,7 @@
- New Event + New Event @@ -17,19 +15,11 @@
Events
- Export to CSV + Export to CSV
- + {% raw %}