API reports and search
This commit is contained in:
@@ -59,6 +59,11 @@ def init_db():
|
|||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT 'Total', COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))), COUNT(*)
|
SELECT 'Total', COUNT(DISTINCT(CONCAT(first_name, last_name, phone_number))), COUNT(*)
|
||||||
FROM tickets""")
|
FROM tickets""")
|
||||||
|
cur.execute("""CREATE VIEW IF NOT EXISTS v_donors AS
|
||||||
|
SELECT bd.b_prefix, bd.b_id, bd.d_id, d.donor_name, d.donor_business, b.description
|
||||||
|
FROM r_basket_donor bd LEFT JOIN donors d ON bd.d_id = d.donor_id
|
||||||
|
LEFT JOIN baskets b ON bd.b_prefix = b.prefix AND bd.b_id = b.basket_id
|
||||||
|
ORDER BY bd.b_prefix, bd.b_id""")
|
||||||
if config["mode"] != "prod":
|
if config["mode"] != "prod":
|
||||||
cur.execute("""REPLACE INTO auth VALUES ('2RO2T7GET9S7X64JUFN67OAV', 'Testing')""")
|
cur.execute("""REPLACE INTO auth VALUES ('2RO2T7GET9S7X64JUFN67OAV', 'Testing')""")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ class BasketDonorRel:
|
|||||||
b_id: int = 0
|
b_id: int = 0
|
||||||
d_id: int = 0
|
d_id: int = 0
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BasketDonorView:
|
||||||
|
b_prefix: str = ""
|
||||||
|
b_id: int = 0
|
||||||
|
d_id: int = 0
|
||||||
|
donor_name: str = ""
|
||||||
|
donor_business: str = ""
|
||||||
|
description: str = ""
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class WinnerByBasket:
|
class WinnerByBasket:
|
||||||
prefix: str = ""
|
prefix: str = ""
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from ..core.models import RepoTemplate
|
from ..core.models import RepoTemplate
|
||||||
from .models import Prefix, Ticket, Count, Basket, WinnerByBasket
|
from .models import Prefix, Ticket, Count, Basket, WinnerByBasket, Donor, BasketDonorView, BasketDonorRel
|
||||||
|
|
||||||
|
|
||||||
class PrefixRepo(RepoTemplate):
|
class PrefixRepo(RepoTemplate):
|
||||||
@@ -156,3 +156,41 @@ class DrawingRepo(RepoTemplate):
|
|||||||
winning_ticket = EXCLUDED.winning_ticket""", (b.prefix, b.basket_id, b.winning_ticket))
|
winning_ticket = EXCLUDED.winning_ticket""", (b.prefix, b.basket_id, b.winning_ticket))
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
return {"detail": "Winners posted successfully."}
|
return {"detail": "Winners posted successfully."}
|
||||||
|
|
||||||
|
class DonorRepo(RepoTemplate):
|
||||||
|
"""Repo that controls Donors."""
|
||||||
|
|
||||||
|
def get_all_donors(self):
|
||||||
|
"""Gets all donors."""
|
||||||
|
self.cur.execute("SELECT * FROM donors")
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [Donor(*r) for r in results]
|
||||||
|
|
||||||
|
def get_donor_relations(self, prefix: str, basket_id: int):
|
||||||
|
"""Get a list of donors for one basket."""
|
||||||
|
self.cur.execute("SELECT * FROM v_donors WHERE b_prefix = ? AND b_id = ?", (prefix, basket_id))
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [BasketDonorView(*r) for r in results]
|
||||||
|
|
||||||
|
def post_donors(self, ds: list[Donor]):
|
||||||
|
"""Posts donors"""
|
||||||
|
rtn_lst = []
|
||||||
|
for d in ds:
|
||||||
|
self.cur.execute("INSERT INTO donors (donor_name, donor_business) VALUES (?, ?) RETURNING *", (d.donor_name, d.donor_business))
|
||||||
|
rtn_lst.append(Donor(*self.cur.fetchone()))
|
||||||
|
self.conn.commit()
|
||||||
|
return rtn_lst
|
||||||
|
|
||||||
|
def post_donor_relation(self, drs: list[BasketDonorRel]):
|
||||||
|
"""Post donor relations."""
|
||||||
|
for dr in drs:
|
||||||
|
self.cur.execute("""INSERT INTO r_basket_donor VALUES (?, ?, ?) ON CONFLICT (b_prefix, b_id, d_id)
|
||||||
|
DO NOTHING""", (dr.b_prefix, dr.b_id, dr.d_id))
|
||||||
|
self.conn.commit()
|
||||||
|
return {"detail": "Relations posted successfully."}
|
||||||
|
|
||||||
|
def del_donor_relation(self, r: BasketDonorRel):
|
||||||
|
"""Delete donor relation."""
|
||||||
|
self.cur.execute("DELETE FROM r_basket_donor WHERE b_prefix = ? AND b_id = ? AND d_id = ?", (r.b_prefix, r.b_id, r.d_id))
|
||||||
|
self.conn.commit()
|
||||||
|
return {"detail": "Relation deleted successfully."}
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
from fastapi import APIRouter, Header, HTTPException, status
|
from fastapi import APIRouter, Header, HTTPException, status
|
||||||
|
|
||||||
from ..core.auth import AuthRepo
|
from ..core.auth import AuthRepo
|
||||||
from .models import Basket, Prefix, Ticket
|
from .models import Basket, BasketDonorRel, Donor, Prefix, Ticket
|
||||||
from .repos import BasketRepo, CountsRepo, DrawingRepo, PrefixRepo, TicketRepo
|
from .repos import (
|
||||||
|
BasketRepo,
|
||||||
|
CountsRepo,
|
||||||
|
DonorRepo,
|
||||||
|
DrawingRepo,
|
||||||
|
PrefixRepo,
|
||||||
|
TicketRepo,
|
||||||
|
)
|
||||||
|
|
||||||
prefix_router = APIRouter(prefix="/api/prefix")
|
prefix_router = APIRouter(prefix="/api/prefix")
|
||||||
|
|
||||||
@@ -164,3 +171,36 @@ def get_drawing_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")):
|
|||||||
def post_winners(bs: list[Basket], tam_auth_key: str = Header("")):
|
def post_winners(bs: list[Basket], tam_auth_key: str = Header("")):
|
||||||
AuthRepo().verify_key(tam_auth_key)
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
return DrawingRepo().post_winners(bs)
|
return DrawingRepo().post_winners(bs)
|
||||||
|
|
||||||
|
|
||||||
|
donor_router = APIRouter(prefix="/api/donors")
|
||||||
|
|
||||||
|
|
||||||
|
@donor_router.get("")
|
||||||
|
def get_all_donors(tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return DonorRepo().get_all_donors()
|
||||||
|
|
||||||
|
|
||||||
|
@donor_router.get("/b/{prefix}/{b_id}")
|
||||||
|
def get_basket_donors(prefix: str, b_id: int, tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return DonorRepo().get_donor_relations(prefix, b_id)
|
||||||
|
|
||||||
|
|
||||||
|
@donor_router.post("/new")
|
||||||
|
def post_donors(ds: list[Donor], tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return DonorRepo().post_donors(ds)
|
||||||
|
|
||||||
|
|
||||||
|
@donor_router.post("/rel")
|
||||||
|
def post_donor_relations(drs: list[BasketDonorRel], tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return DonorRepo().post_donor_relation(drs)
|
||||||
|
|
||||||
|
|
||||||
|
@donor_router.delete("/rel")
|
||||||
|
def delete_donor_relation(r: BasketDonorRel, tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return DonorRepo().del_donor_relation(r)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
from ..core.models import RepoTemplate
|
||||||
|
from ..data.models import WinnerByBasket, WinnerByName, BasketDonorView
|
||||||
|
|
||||||
|
class ReportsRepo(RepoTemplate):
|
||||||
|
"""Repo that controls all report functions."""
|
||||||
|
|
||||||
|
def get_winners_by_basket(self, prefix: str):
|
||||||
|
"""Gets prefix winners by basket."""
|
||||||
|
self.cur.execute("SELECT * FROM winners_by_basket WHERE prefix = ?", (prefix,))
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [WinnerByBasket(*r) for r in results]
|
||||||
|
|
||||||
|
def get_winners_by_name(self, prefix: str):
|
||||||
|
"""Gets prefix winners by name."""
|
||||||
|
self.cur.execute("SELECT * FROM winners_by_name WHERE prefix = ?", (prefix,))
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [WinnerByName(*r) for r in results]
|
||||||
|
|
||||||
|
def get_donor_contributions(self):
|
||||||
|
"""Gets all donor contributions."""
|
||||||
|
self.cur.execute("SELECT * FROM v_donors")
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [BasketDonorView(*r) for r in results]
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from fastapi import APIRouter, Header
|
||||||
|
from .repos import ReportsRepo
|
||||||
|
from ..core.auth import AuthRepo
|
||||||
|
|
||||||
|
reports_router = APIRouter(prefix="/api/reports")
|
||||||
|
|
||||||
|
@reports_router.get("/winners/bybasket/{prefix}")
|
||||||
|
def get_winners_by_basket(prefix: str, tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return ReportsRepo().get_winners_by_basket(prefix)
|
||||||
|
|
||||||
|
@reports_router.get("/winners/byname/{prefix}")
|
||||||
|
def get_winners_by_name(prefix: str, tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return ReportsRepo().get_winners_by_name(prefix)
|
||||||
|
|
||||||
|
@reports_router.get("/donors/contrib")
|
||||||
|
def get_donor_contributions(tam_auth_key: str = Header("")):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return ReportsRepo().get_donor_contributions()
|
||||||
@@ -2,6 +2,8 @@ from fastapi import FastAPI
|
|||||||
|
|
||||||
from .core.auth import auth_router
|
from .core.auth import auth_router
|
||||||
from .data import routers
|
from .data import routers
|
||||||
|
from .reports import routers as report_routers
|
||||||
|
from .search import routers as search_routers
|
||||||
|
|
||||||
def append_routers(app: FastAPI):
|
def append_routers(app: FastAPI):
|
||||||
app.include_router(auth_router)
|
app.include_router(auth_router)
|
||||||
@@ -10,3 +12,6 @@ def append_routers(app: FastAPI):
|
|||||||
app.include_router(routers.counts_router)
|
app.include_router(routers.counts_router)
|
||||||
app.include_router(routers.basket_router)
|
app.include_router(routers.basket_router)
|
||||||
app.include_router(routers.drawing_router)
|
app.include_router(routers.drawing_router)
|
||||||
|
app.include_router(routers.donor_router)
|
||||||
|
app.include_router(report_routers.reports_router)
|
||||||
|
app.include_router(search_routers.search_router)
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from ..core.models import RepoTemplate
|
||||||
|
from ..data.models import Ticket
|
||||||
|
|
||||||
|
|
||||||
|
class SearchRepo(RepoTemplate):
|
||||||
|
"""Repo that controls search."""
|
||||||
|
|
||||||
|
def search_tickets(
|
||||||
|
self, first_name: str = "", last_name: str = "", phone_number: str = ""
|
||||||
|
):
|
||||||
|
"""Searches tickets for a specific name."""
|
||||||
|
self.cur.execute(
|
||||||
|
"""SELECT * FROM tickets
|
||||||
|
WHERE first_name LIKE ? AND last_name LIKE ? AND phone_number LIKE ?
|
||||||
|
ORDER BY prefix, ticket_id""",
|
||||||
|
(f"%{first_name}%", f"%{last_name}%", f"%{phone_number}%"),
|
||||||
|
)
|
||||||
|
results = self.cur.fetchall()
|
||||||
|
return [Ticket(*r) for r in results]
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from fastapi import APIRouter, Header
|
||||||
|
from .repo import SearchRepo
|
||||||
|
from ..core.auth import AuthRepo
|
||||||
|
|
||||||
|
search_router = APIRouter(prefix="/api/search")
|
||||||
|
|
||||||
|
@search_router.get("/tickets")
|
||||||
|
def search_tickets(
|
||||||
|
first_name: str = "", last_name: str = "", phone_number: str = "", tam_auth_key: str = Header("")
|
||||||
|
):
|
||||||
|
AuthRepo().verify_key(tam_auth_key)
|
||||||
|
return SearchRepo().search_tickets(first_name, last_name, phone_number)
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
localhost:8443 {
|
||||||
|
reverse_proxy localhost:8000
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user