diff --git a/api/.gitignore b/api/.gitignore index 6ca7b68..a8149f9 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -1,2 +1,3 @@ /data -*/__pycache__ +__pycache__/ +*.pyc diff --git a/api/app/data/__pycache__/baskets.cpython-314.pyc b/api/app/data/__pycache__/baskets.cpython-314.pyc deleted file mode 100644 index 1568686..0000000 Binary files a/api/app/data/__pycache__/baskets.cpython-314.pyc and /dev/null differ diff --git a/api/app/data/__pycache__/drawing.cpython-314.pyc b/api/app/data/__pycache__/drawing.cpython-314.pyc deleted file mode 100644 index 5d8137f..0000000 Binary files a/api/app/data/__pycache__/drawing.cpython-314.pyc and /dev/null differ diff --git a/api/app/data/__pycache__/tickets.cpython-314.pyc b/api/app/data/__pycache__/tickets.cpython-314.pyc deleted file mode 100644 index 9e9e591..0000000 Binary files a/api/app/data/__pycache__/tickets.cpython-314.pyc and /dev/null differ diff --git a/api/app/data/reports.py b/api/app/data/reports.py new file mode 100644 index 0000000..8c95fea --- /dev/null +++ b/api/app/data/reports.py @@ -0,0 +1,50 @@ +from dataclasses import dataclass +from db import RepoTemplate +from system.auth import AuthRepo +from fastapi import APIRouter, Header + +@dataclass +class ReportByNameLine: + last_name: str = "" + first_name: str = "" + phone_number: str = "" + pref: str = "" + prefix: str = "" + b_id: int = 0 + description: str = "" + donors: str = "" + winning_ticket: int = 0 + +@dataclass +class ReportByBasketLine: + prefix: str = "" + b_id: int = 0 + description: str = "" + donors: str = "" + winning_ticket: int = 0 + last_name: str = "" + first_name: str = "" + phone_number: str = "" + pref: str = "" + +class ReportsRepo(RepoTemplate): + def get_by_name_report(self, prefix: str): + self.cur.execute("SELECT * FROM report_by_name WHERE prefix = ?", (prefix,)) + results = self.cur.fetchall() + return [ReportByNameLine(*r) for r in results] + def get_by_basket_report(self, prefix: str): + self.cur.execute("SELECT * FROM report_by_basket WHERE prefix = ?", (prefix,)) + results = self.cur.fetchall() + return [ReportByBasketLine(*r) for r in results] + +reports_router = APIRouter(prefix="/api/reports") + +@reports_router.get("/byname/{prefix}") +def get_report_by_name(prefix: str, tam_key: str = Header("")): + AuthRepo().verify_key(tam_key) + return ReportsRepo().get_by_name_report(prefix) + +@reports_router.get("/bybasket/{prefix}") +def get_report_by_basket(prefix: str, tam_key: str = Header("")): + AuthRepo().verify_key(tam_key) + return ReportsRepo().get_by_basket_report(prefix) diff --git a/api/app/db.py b/api/app/db.py index cf31e1e..474bb7d 100644 --- a/api/app/db.py +++ b/api/app/db.py @@ -25,6 +25,14 @@ def init_db(): SELECT b.prefix, b.b_id, b.description, b.winning_ticket, t.last_name, t.first_name, t.phone_number FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id ORDER BY b.prefix, b.b_id""") + cur.execute("""CREATE VIEW IF NOT EXISTS report_by_name AS + SELECT t.last_name, t.first_name, t.phone_number, t.pref, b.* + FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id + ORDER BY t.last_name, t.first_name, t.phone_number, b.prefix, b.b_id""") + cur.execute("""CREATE VIEW IF NOT EXISTS report_by_basket AS + SELECT b.*, t.last_name, t.first_name, t.phone_number, t.pref + FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id + ORDER BY b.prefix, b.b_id""") conn.commit() conn.close() diff --git a/api/app/routers.py b/api/app/routers.py index 320a1a6..25806fe 100644 --- a/api/app/routers.py +++ b/api/app/routers.py @@ -4,6 +4,7 @@ from system.prefixes import prefix_router from data.tickets import tickets_router from data.baskets import basket_router from data.drawing import drawing_router +from data.reports import reports_router def imp_routers(app: FastAPI): app.include_router(auth_router) @@ -11,3 +12,4 @@ def imp_routers(app: FastAPI): app.include_router(tickets_router) app.include_router(basket_router) app.include_router(drawing_router) + app.include_router(reports_router) diff --git a/client/src/lib/server/db/schema.js b/client/src/lib/server/db/schema.js index 819b900..129d6a8 100644 --- a/client/src/lib/server/db/schema.js +++ b/client/src/lib/server/db/schema.js @@ -43,3 +43,31 @@ export const drawing = sqliteView('drawing', { }).as(sql`SELECT b.prefix, b.b_id, b.description, b.winning_ticket, t.last_name, t.first_name, t.phone_number FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id ORDER BY b.prefix, b.b_id`) + +export const reportByName = sqliteView('report_by_name', { + last_name: text('last_name'), + first_name: text('first_name'), + phone_number: text('phone_number'), + pref: text('pref'), + prefix: text('prefix'), + b_id: integer('b_id'), + description: text('description'), + donors: text('donors'), + winning_ticket: integer('winning_ticket') +}).as(sql`SELECT t.last_name, t.first_name, t.phone_number, t.pref, b.prefix, b.b_id, b.description, b.donors, b.winning_ticket + FROM baskets b LEFT JOIN tickets t ON b.prefix = t.prefix AND b.winning_ticket = t.t_id + ORDER BY t.last_name, t.first_name, t.phone_number, b.prefix, b.b_id`) + +export const reportByBasket = sqliteView('report_by_basket', { + prefix: text('prefix'), + b_id: integer('b_id'), + description: text('description'), + donors: text('donors'), + winning_ticket: integer('winning_ticket'), + last_name: text('last_name'), + first_name: text('first_name'), + phone_number: text('phone_number'), + pref: text('pref') +}).as(sql`SELECT b.prefix, b.b_id, b.description, b.donors, b.winning_ticket, t.last_name, t.first_name, t.phone_number, t.pref + FROM baskets b LEFT JOIN tickets t on b.prefix = t.prefix AND b.winning_ticket = t.t_id + ORDER BY b.prefix, b.b_id`) diff --git a/client/src/routes/api/reports/bybasket/[prefix]/+server.js b/client/src/routes/api/reports/bybasket/[prefix]/+server.js new file mode 100644 index 0000000..478e900 --- /dev/null +++ b/client/src/routes/api/reports/bybasket/[prefix]/+server.js @@ -0,0 +1,24 @@ +import { db } from '$lib/server/db/index.js'; +import { reportByBasket } from '$lib/server/db/schema.js'; +import { getPath, getSettings } from '$lib/server/settings'; +import { error, json } from '@sveltejs/kit'; +import { eq } from 'drizzle-orm'; + +export const GET = async ({ params }) => { + const { prefix } = params; + const s = getSettings(); + if (s.remote_server) { + const connStr = getPath(s); + try { + const res = await fetch(`${connStr}/api/reports/bybasket/${prefix}`, {headers: {'TAM-KEY': s.remote_key}}); + if (!res.ok) throw error(res.status); + const data = await res.json(); + return json(data); + } catch { + return json([]); + } + } else { + const data = await db.select().from(reportByBasket).where(eq(reportByBasket.prefix, prefix)); + return json(data); + } +} diff --git a/client/src/routes/api/reports/byname/[prefix]/+server.js b/client/src/routes/api/reports/byname/[prefix]/+server.js new file mode 100644 index 0000000..b59be8c --- /dev/null +++ b/client/src/routes/api/reports/byname/[prefix]/+server.js @@ -0,0 +1,24 @@ +import { db } from '$lib/server/db/index.js'; +import { reportByName } from '$lib/server/db/schema.js'; +import { getPath, getSettings } from '$lib/server/settings'; +import { error, json } from '@sveltejs/kit'; +import { eq } from 'drizzle-orm'; + +export const GET = async ({ params }) => { + const { prefix } = params; + const s = getSettings(); + if (s.remote_server) { + const connStr = getPath(s); + try { + const res = await fetch(`${connStr}/api/reports/byname/${prefix}`, {headers: {'TAM-KEY': s.remote_key}}); + if (!res.ok) throw error(res.status); + const data = await res.json(); + return json(data); + } catch { + return json([]); + } + } else { + const data = await db.select().from(reportByName).where(eq(reportByName.prefix, prefix)); + return json(data); + } +}