feat: podpora simulace objednávek z Bolt Food ve vývoji

This commit is contained in:
2026-06-12 19:44:20 +02:00
parent bcec015c37
commit 34f6ba520e
13 changed files with 662 additions and 4 deletions
+80
View File
@@ -6,6 +6,12 @@ import { getWebsocket } from "../websocket";
import { getLogin } from "../auth";
import { parseToken } from "../utils";
import webpush from 'web-push';
import { ClientData, GroupState } from "../../../types/gen/types.gen";
import {
startBoltSimulation, advanceBoltSimulation, setBoltSimulationStep,
stopBoltSimulationByGroup, getBoltSimulation,
} from "../boltSimulator";
import { checkBoltTracking } from "../boltTracking";
const router = express.Router();
const storage = getStorage();
@@ -195,4 +201,78 @@ router.post("/testPush", async (req, res, next) => {
} catch (e: any) { next(e) }
});
// --- DEV simulace sledování Bolt Food ---
/** Nastaví/zruší sledovací token skupiny a zajistí stav ORDERED. Vrátí aktualizovaná data. */
async function applyBoltToken(groupId: string, token: string | undefined): Promise<ClientData> {
const key = `${formatDate(getToday())}_extra`;
return storage.updateData<ClientData>(key, current => {
const d = current;
const group = d?.groups?.find(g => g.id === groupId);
if (!group) throw new Error('Skupina nebyla nalezena');
group.boltTrackingToken = token;
if (token) {
group.state = GroupState.ORDERED;
} else {
group.boltOrderState = undefined;
group.boltCourierState = undefined;
}
return d!;
});
}
/** Spustí simulaci sledování Bolt pro skupinu a provede první poll. */
router.post("/bolt/simulate", async (req: Request<{}, any, any>, res, next) => {
try {
const groupId = req.body?.groupId;
if (!groupId) return res.status(400).json({ error: 'Chybí groupId' });
const token = startBoltSimulation(groupId);
await applyBoltToken(groupId, token);
await checkBoltTracking(); // okamžitý první poll → stav "accepted" + websocket
res.status(200).json({ success: true, token, simulation: getBoltSimulation(groupId) });
} catch (e: any) { next(e); }
});
/** Posune simulaci na další krok a přepošle aktualizovaný stav klientům. */
router.post("/bolt/advance", async (req: Request<{}, any, any>, res, next) => {
try {
const groupId = req.body?.groupId;
if (!groupId) return res.status(400).json({ error: 'Chybí groupId' });
advanceBoltSimulation(groupId);
await checkBoltTracking();
res.status(200).json({ success: true, simulation: getBoltSimulation(groupId) });
} catch (e: any) { next(e); }
});
/** Nastaví konkrétní stav simulace (ruční override, např. pro stav "cancelled"). */
router.post("/bolt/state", async (req: Request<{}, any, any>, res, next) => {
try {
const { groupId, order_state, courier_state, etaSeconds } = req.body ?? {};
if (!groupId || !order_state) return res.status(400).json({ error: 'Chybí groupId nebo order_state' });
setBoltSimulationStep(groupId, { order_state, courier_state, etaSeconds });
await checkBoltTracking();
res.status(200).json({ success: true, simulation: getBoltSimulation(groupId) });
} catch (e: any) { next(e); }
});
/** Spustí jeden tik scheduleru okamžitě (bez čekání na interval). */
router.post("/bolt/poll", async (_req, res, next) => {
try {
await checkBoltTracking();
res.status(200).json({ success: true });
} catch (e: any) { next(e); }
});
/** Ukončí simulaci skupiny a odebere sledovací token. */
router.delete("/bolt/simulate", async (req: Request<{}, any, any>, res, next) => {
try {
const groupId = req.body?.groupId;
if (!groupId) return res.status(400).json({ error: 'Chybí groupId' });
stopBoltSimulationByGroup(groupId);
const updated = await applyBoltToken(groupId, undefined);
getWebsocket()?.emit('message', updated);
res.status(200).json({ success: true });
} catch (e: any) { next(e); }
});
export default router;