feat: trvalé zobrazení QR kódu do ručního zavření (#31)
QR kódy pro platbu za pizza day jsou nyní zobrazeny persistentně i po následující dny, dokud uživatel nepotvrdí platbu tlačítkem "Zaplatil jsem". Nevyřízené QR kódy jsou uloženy per-user v storage a zobrazeny v sekci "Nevyřízené platby".
This commit is contained in:
@@ -5,8 +5,9 @@ import { getData, getDateForWeekIndex, getToday } from "./service";
|
||||
import dotenv from 'dotenv';
|
||||
import path from 'path';
|
||||
import { getQr } from "./qr";
|
||||
import { generateToken, verify } from "./auth";
|
||||
import { getIsWeekend, InsufficientPermissions } from "./utils";
|
||||
import { generateToken, getLogin, verify } from "./auth";
|
||||
import { getIsWeekend, InsufficientPermissions, parseToken } from "./utils";
|
||||
import { getPendingQrs } from "./pizza";
|
||||
import { initWebsocket } from "./websocket";
|
||||
import pizzaDayRoutes from "./routes/pizzaDayRoutes";
|
||||
import foodRoutes, { refreshMetoda } from "./routes/foodRoutes";
|
||||
@@ -138,7 +139,18 @@ app.get("/api/data", async (req, res) => {
|
||||
// Na víkendu zobrazíme pátek místo hlášky "Užívejte víkend"
|
||||
date = getDateForWeekIndex(4);
|
||||
}
|
||||
res.status(200).json(await getData(date));
|
||||
const data = await getData(date);
|
||||
// Připojíme nevyřízené QR kódy pro přihlášeného uživatele
|
||||
try {
|
||||
const login = getLogin(parseToken(req));
|
||||
const pendingQrs = await getPendingQrs(login);
|
||||
if (pendingQrs.length > 0) {
|
||||
data.pendingQrs = pendingQrs;
|
||||
}
|
||||
} catch {
|
||||
// Token nemusí být validní, ignorujeme
|
||||
}
|
||||
res.status(200).json(data);
|
||||
});
|
||||
|
||||
// Ostatní routes
|
||||
|
||||
@@ -4,9 +4,10 @@ import { generateQr } from "./qr";
|
||||
import getStorage from "./storage";
|
||||
import { downloadPizzy } from "./chefie";
|
||||
import { getClientData, getToday, initIfNeeded } from "./service";
|
||||
import { Pizza, ClientData, PizzaDayState, PizzaSize, PizzaOrder, PizzaVariant, UdalostEnum } from "../../types/gen/types.gen";
|
||||
import { Pizza, ClientData, PizzaDayState, PizzaSize, PizzaOrder, PizzaVariant, UdalostEnum, PendingQr } from "../../types/gen/types.gen";
|
||||
|
||||
const storage = getStorage();
|
||||
const PENDING_QR_PREFIX = 'pending_qr';
|
||||
|
||||
/**
|
||||
* Vrátí seznam dostupných pizz pro dnešní den.
|
||||
@@ -241,6 +242,12 @@ export async function finishPizzaDelivery(login: string, bankAccount?: string, b
|
||||
let message = order.pizzaList!.map(pizza => `Pizza ${pizza.name} (${pizza.size})`).join(', ');
|
||||
await generateQr(order.customer, bankAccount, bankAccountHolder, order.totalPrice, message);
|
||||
order.hasQr = true;
|
||||
// Uložíme nevyřízený QR kód pro persistentní zobrazení
|
||||
await addPendingQr(order.customer, {
|
||||
date: today,
|
||||
creator: login,
|
||||
totalPrice: order.totalPrice,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -307,4 +314,41 @@ export async function updatePizzaFee(login: string, targetLogin: string, text?:
|
||||
targetOrder.totalPrice = targetOrder.pizzaList.reduce((price, pizzaOrder) => price + pizzaOrder.price, 0) + (targetOrder.fee?.price ?? 0);
|
||||
await storage.setData(today, clientData);
|
||||
return clientData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vrátí klíč pro uložení nevyřízených QR kódů uživatele.
|
||||
*/
|
||||
function getPendingQrKey(login: string): string {
|
||||
return `${PENDING_QR_PREFIX}_${login}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Přidá nevyřízený QR kód pro uživatele.
|
||||
*/
|
||||
async function addPendingQr(login: string, pendingQr: PendingQr): Promise<void> {
|
||||
const key = getPendingQrKey(login);
|
||||
const existing = await storage.getData<PendingQr[]>(key) ?? [];
|
||||
// Nepřidáváme duplicity pro stejný den
|
||||
if (!existing.some(qr => qr.date === pendingQr.date)) {
|
||||
existing.push(pendingQr);
|
||||
await storage.setData(key, existing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vrátí nevyřízené QR kódy pro uživatele.
|
||||
*/
|
||||
export async function getPendingQrs(login: string): Promise<PendingQr[]> {
|
||||
return await storage.getData<PendingQr[]>(getPendingQrKey(login)) ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Označí QR kód pro daný den jako uhrazený (odstraní ho ze seznamu nevyřízených).
|
||||
*/
|
||||
export async function dismissPendingQr(login: string, date: string): Promise<void> {
|
||||
const key = getPendingQrKey(login);
|
||||
const existing = await storage.getData<PendingQr[]>(key) ?? [];
|
||||
const filtered = existing.filter(qr => qr.date !== date);
|
||||
await storage.setData(key, filtered);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import express, { Request } from "express";
|
||||
import { getLogin } from "../auth";
|
||||
import { createPizzaDay, deletePizzaDay, getPizzaList, addPizzaOrder, removePizzaOrder, lockPizzaDay, unlockPizzaDay, finishPizzaOrder, finishPizzaDelivery, updatePizzaDayNote, updatePizzaFee } from "../pizza";
|
||||
import { createPizzaDay, deletePizzaDay, getPizzaList, addPizzaOrder, removePizzaOrder, lockPizzaDay, unlockPizzaDay, finishPizzaOrder, finishPizzaDelivery, updatePizzaDayNote, updatePizzaFee, dismissPendingQr } from "../pizza";
|
||||
import { parseToken } from "../utils";
|
||||
import { getWebsocket } from "../websocket";
|
||||
import { AddPizzaData, FinishDeliveryData, RemovePizzaData, UpdatePizzaDayNoteData, UpdatePizzaFeeData } from "../../../types";
|
||||
import { AddPizzaData, DismissQrData, FinishDeliveryData, RemovePizzaData, UpdatePizzaDayNoteData, UpdatePizzaFeeData } from "../../../types";
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -109,4 +109,16 @@ router.post("/updatePizzaFee", async (req: Request<{}, any, UpdatePizzaFeeData["
|
||||
} catch (e: any) { next(e) }
|
||||
});
|
||||
|
||||
/** Označí QR kód jako uhrazený. */
|
||||
router.post("/dismissQr", async (req: Request<{}, any, DismissQrData["body"]>, res, next) => {
|
||||
const login = getLogin(parseToken(req));
|
||||
if (!req.body.date) {
|
||||
return res.status(400).json({ error: "Nebyl předán datum" });
|
||||
}
|
||||
try {
|
||||
await dismissPendingQr(login, req.body.date);
|
||||
res.status(200).json({});
|
||||
} catch (e: any) { next(e) }
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user