diff --git a/server/src/service.ts b/server/src/service.ts index 2bf7887..4de8c60 100644 --- a/server/src/service.ts +++ b/server/src/service.ts @@ -76,13 +76,105 @@ async function getMenu(date: Date): Promise { } // TODO přesun do restaurants.ts +/** + * Načte menu dané restaurace pro celý týden bez ukládání do storage. + * Používá se pro validaci dat před uložením. + * + * @param restaurant restaurace + * @param firstDay první pracovní den týdne + * @returns pole menu pro jednotlivé dny týdne + */ +export async function fetchRestaurantWeekMenuData(restaurant: Restaurant, firstDay: Date): Promise { + return await fetchRestaurantWeekMenu(restaurant, firstDay); +} + +/** + * Uloží týdenní menu restaurace do storage. + * + * @param restaurant restaurace + * @param date datum z týdne, pro který ukládat menu + * @param weekData data týdenního menu + */ +export async function saveRestaurantWeekMenu(restaurant: Restaurant, date: Date, weekData: any[]): Promise { + const now = new Date().getTime(); + let weekMenu = await getMenu(date); + weekMenu ??= [{}, {}, {}, {}, {}]; + + // Inicializace struktury pro restauraci + for (let i = 0; i < 5; i++) { + weekMenu[i] ??= {}; + weekMenu[i][restaurant] ??= { + lastUpdate: now, + closed: false, + food: [], + }; + } + + // Uložení dat pro všechny dny + for (let i = 0; i < weekData.length && i < weekMenu.length; i++) { + weekMenu[i][restaurant]!.food = weekData[i]; + weekMenu[i][restaurant]!.lastUpdate = now; + + // Detekce uzavření pro každou restauraci + switch (restaurant) { + case 'SLADOVNICKA': + if (weekData[i].length === 1 && weekData[i][0].name.toLowerCase() === 'pro daný den nebyla nalezena denní nabídka') { + weekMenu[i][restaurant]!.closed = true; + } + break; + case 'TECHTOWER': + if (weekData[i]?.length === 1 && weekData[i][0].name.toLowerCase() === 'svátek') { + weekMenu[i][restaurant]!.closed = true; + } + break; + case 'ZASTAVKAUMICHALA': + if (weekData[i]?.length === 1 && weekData[i][0].name === 'Pro tento den není uveřejněna nabídka jídel.') { + weekMenu[i][restaurant]!.closed = true; + } + break; + case 'SENKSERIKOVA': + if (weekData[i]?.length === 1 && weekData[i][0].name === 'Pro tento den nebylo zadáno menu.') { + weekMenu[i][restaurant]!.closed = true; + } + break; + } + } + + // Uložení do storage + await storage.setData(getMenuKey(date), weekMenu); +} + +/** + * Načte menu dané restaurace pro celý týden bez ukládání do storage. + * + * @param restaurant restaurace + * @param firstDay první pracovní den týdne + * @returns pole menu pro jednotlivé dny týdne + */ +async function fetchRestaurantWeekMenu(restaurant: Restaurant, firstDay: Date): Promise { + const mock = process.env.MOCK_DATA === 'true'; + + switch (restaurant) { + case 'SLADOVNICKA': + return await getMenuSladovnicka(firstDay, mock); + case 'TECHTOWER': + return await getMenuTechTower(firstDay, mock); + case 'ZASTAVKAUMICHALA': + return await getMenuZastavkaUmichala(firstDay, mock); + case 'SENKSERIKOVA': + return await getMenuSenkSerikova(firstDay, mock); + default: + throw new Error(`Nepodporovaná restaurace: ${restaurant}`); + } +} + /** * Vrátí menu dané restaurace pro předaný den. * Pokud neexistuje, provede stažení menu pro příslušný týden a uložení do DB. * * @param restaurant restaurace * @param date datum, ke kterému získat menu - * @param mock příznak, zda chceme pouze mock data + * @param forceRefresh příznak vynuceného obnovení */ export async function getRestaurantMenu(restaurant: Restaurant, date?: Date, forceRefresh = false): Promise { const usedDate = date ?? getToday(); @@ -108,83 +200,45 @@ export async function getRestaurantMenu(restaurant: Restaurant, date?: Date, for } if (forceRefresh || !weekMenu[dayOfWeekIndex][restaurant]?.food?.length) { const firstDay = getFirstWorkDayOfWeek(usedDate); - const mock = process.env.MOCK_DATA === 'true'; - switch (restaurant) { - case 'SLADOVNICKA': - try { - const sladovnickaFood = await getMenuSladovnicka(firstDay, mock); - for (let i = 0; i < sladovnickaFood.length; i++) { - weekMenu[i][restaurant]!.food = sladovnickaFood[i]; - weekMenu[i][restaurant]!.lastUpdate = now; - // Velice chatrný a nespolehlivý způsob detekce uzavření... - if (sladovnickaFood[i].length === 1 && sladovnickaFood[i][0].name.toLowerCase() === 'pro daný den nebyla nalezena denní nabídka') { + + try { + const restaurantWeekFood = await fetchRestaurantWeekMenu(restaurant, firstDay); + + // Aktualizace menu pro všechny dny + for (let i = 0; i < restaurantWeekFood.length && i < weekMenu.length; i++) { + weekMenu[i][restaurant]!.food = restaurantWeekFood[i]; + weekMenu[i][restaurant]!.lastUpdate = now; + + // Detekce uzavření pro každou restauraci + switch (restaurant) { + case 'SLADOVNICKA': + if (restaurantWeekFood[i].length === 1 && restaurantWeekFood[i][0].name.toLowerCase() === 'pro daný den nebyla nalezena denní nabídka') { weekMenu[i][restaurant]!.closed = true; } - } - } catch (e: any) { - console.error("Selhalo načtení jídel pro podnik Sladovnická", e); - } - break; - // case 'UMOTLIKU': - // try { - // const uMotlikuFood = await getMenuUMotliku(firstDay, mock); - // for (let i = 0; i < uMotlikuFood.length; i++) { - // menus[i][restaurant]!.food = uMotlikuFood[i]; - // if (uMotlikuFood[i].length === 1 && uMotlikuFood[i][0].name.toLowerCase() === 'zavřeno') { - // menus[i][restaurant]!.closed = true; - // } - // } - // } catch (e: any) { - // console.error("Selhalo načtení jídel pro podnik U Motlíků", e); - // } - // break; - case 'TECHTOWER': - try { - const techTowerFood = await getMenuTechTower(firstDay, mock); - for (let i = 0; i < techTowerFood.length; i++) { - weekMenu[i][restaurant]!.food = techTowerFood[i]; - weekMenu[i][restaurant]!.lastUpdate = now; - if (techTowerFood[i]?.length === 1 && techTowerFood[i][0].name.toLowerCase() === 'svátek') { + break; + case 'TECHTOWER': + if (restaurantWeekFood[i]?.length === 1 && restaurantWeekFood[i][0].name.toLowerCase() === 'svátek') { weekMenu[i][restaurant]!.closed = true; } - } - } catch (e: any) { - console.error("Selhalo načtení jídel pro podnik TechTower", e); - } - break; - case 'ZASTAVKAUMICHALA': - try { - const zastavkaUmichalaFood = await getMenuZastavkaUmichala(firstDay, mock); - for (let i = 0; i < zastavkaUmichalaFood.length; i++) { - weekMenu[i][restaurant]!.food = zastavkaUmichalaFood[i]; - weekMenu[i][restaurant]!.lastUpdate = now; - if (zastavkaUmichalaFood[i]?.length === 1 && zastavkaUmichalaFood[i][0].name === 'Pro tento den není uveřejněna nabídka jídel.') { + break; + case 'ZASTAVKAUMICHALA': + if (restaurantWeekFood[i]?.length === 1 && restaurantWeekFood[i][0].name === 'Pro tento den není uveřejněna nabídka jídel.') { weekMenu[i][restaurant]!.closed = true; } - } - } catch (e: any) { - console.error("Selhalo načtení jídel pro podnik Zastávka u Michala", e); - } - break; - case 'SENKSERIKOVA': - try { - const senkSerikovaFood = await getMenuSenkSerikova(firstDay, mock); - for (let i = 0; i < senkSerikovaFood.length; i++) { - if (i >= weekMenu.length) { - break; - } - weekMenu[i][restaurant]!.food = senkSerikovaFood[i]; - weekMenu[i][restaurant]!.lastUpdate = now; - if (senkSerikovaFood[i]?.length === 1 && senkSerikovaFood[i][0].name === 'Pro tento den nebylo zadáno menu.') { + break; + case 'SENKSERIKOVA': + if (restaurantWeekFood[i]?.length === 1 && restaurantWeekFood[i][0].name === 'Pro tento den nebylo zadáno menu.') { weekMenu[i][restaurant]!.closed = true; } - } - } catch (e: any) { - console.error("Selhalo načtení jídel pro podnik Pivovarský šenk Šeříková", e); + break; } - break; + } + + // Uložení do storage + await storage.setData(getMenuKey(usedDate), weekMenu); + } catch (e: any) { + console.error(`Selhalo načtení jídel pro podnik ${restaurant}`, e); } - await storage.setData(getMenuKey(usedDate), weekMenu); } return weekMenu[dayOfWeekIndex][restaurant]!; }