- getPlanningForDate(houseId, date: DateTime) — paramétré au lieu de toujours "aujourd'hui", même logique de recherche sinon - GET /planning?date=YYYY-MM-DD, validation de forme (zod) puis de validité calendaire (parseDateOnly, 400 VALIDATION_ERROR sinon) — un seul endpoint générique au lieu de deux qui se recouvrent - Tests Mocha + Cucumber adaptés, + cas date manquante/malformée/ impossible et "semaine différente d'aujourd'hui"
65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
import { type DateTime, toDateOnly } from "@batch-cooking/date-tools";
|
|
import type { PlanningView } from "@batch-cooking/shared";
|
|
import { prisma } from "../../db/prisma.js";
|
|
|
|
/**
|
|
* Finds the household's planning that covers `date` and shapes it into a
|
|
* {@link PlanningView} (recipes resolved to `{id, name}`). `date` is
|
|
* whatever the caller wants "now" to mean — the current `/planning` route
|
|
* passes a `date-tools`-parsed `?date=` query param, letting a caller look
|
|
* up any week's planning, not just the one covering today.
|
|
*
|
|
* Returns `null` for two distinct, both entirely normal states — a
|
|
* `houseId` of `null` (the profile has no household yet — households are no
|
|
* longer created automatically at signup, see `auth.service.ts`) and "no
|
|
* planning row covers this date" (the expected case until planning
|
|
* creation is built) — neither is an error, so both collapse to the same
|
|
* "nothing to show yet" result rather than throwing.
|
|
*/
|
|
export async function getPlanningForDate(
|
|
houseId: number | null,
|
|
date: DateTime,
|
|
): Promise<PlanningView | null> {
|
|
if (houseId === null) {
|
|
return null;
|
|
}
|
|
|
|
// `startDate`/`finishDate` are `@db.Date` columns (no time-of-day
|
|
// component) — comparing against a UTC-midnight JS `Date` lines up with
|
|
// how Postgres stores/returns them, regardless of the server's local
|
|
// timezone.
|
|
const dateOnly = toDateOnly(date).toJSDate();
|
|
|
|
const planning = await prisma.planning.findFirst({
|
|
where: {
|
|
houseId,
|
|
startDate: { lte: dateOnly },
|
|
finishDate: { gte: dateOnly },
|
|
},
|
|
// A household should never have two plannings covering the same day,
|
|
// but nothing in the schema enforces that yet — pick the most recently
|
|
// started one rather than letting the query fail if it ever happens.
|
|
orderBy: { startDate: "desc" },
|
|
include: {
|
|
items: {
|
|
include: { recipe: { select: { id: true, name: true } } },
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!planning) {
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: planning.id,
|
|
startDate: planning.startDate.toISOString(),
|
|
finishDate: planning.finishDate.toISOString(),
|
|
items: planning.items.map((item) => ({
|
|
id: item.id,
|
|
weekDay: item.weekDay,
|
|
meal: item.meal,
|
|
recipe: item.recipe,
|
|
})),
|
|
};
|
|
}
|