fix(veckoplan+streckkod): byt ratt, planera om, variation, man-son + fota fram/bak
Veckoplan/kalender: - Byt ratt: PATCH satter nu titeln (och portioner/status) efter det nya receptet, inte bara recipeId - annars visade kalendern kvar gamla ratten. - Planera om veckan: ersatter nu veckans plan (raderar tidigare + entries via kaskad) sa man aldrig far dubbletter och alltid ser den nya planen. Nytt plan-id ger ocksa ny variation. - Variation: liten deterministisk jitter per recept, seedad pa plan-id + veckostart, sa olika veckor OCH omgenereringar blir olika. Tackning/utgang dominerar fortfarande. Skalas av varietyLevel. - Veckoplaneraren visar alltid mandag-sondag (mondayOf), oavsett dagens dag. Streckkod (fota okand produkt): - Fotar nu fram- OCH baksida (multi-foto) sa AI:n far bade namn (fram) och naring/innehall (bak). Prompt uppdaterad for flera bilder. - Worker uppdaterar en befintlig delad produkt aven utan nytt namn (behaller namnet, fyller pa naring/innehall/allergener) - och sparar ny produkt aven fran baksidesfoto (fallback-namn) sa data inte tappas. - Produktpanelen visar 'Fota baksidan (naring & innehall)' nar info saknas, sa man kan komplettera en halvfardig produkt. Fel visas som dialog utan att tappa vyn. - 5 nya i18n-nycklar x 12 sprak. Verifierat: typecheck (ai-contracts/worker/api/mobil), worker 23/23, ai-contracts 24/24, api 104/104, samt repro mot testdatabas (byt ratt satter titel; planera om ger 1 plan; 3 veckor + omgenerering varierar; delvis produkt kompletteras och behaller namnet).
This commit is contained in:
@@ -30,7 +30,7 @@ export async function planningRoutes(app: FastifyInstance) {
|
||||
.select()
|
||||
.from(schema.weekPlans)
|
||||
.where(and(...conditions))
|
||||
.orderBy(desc(schema.weekPlans.weekStartDate))
|
||||
.orderBy(desc(schema.weekPlans.weekStartDate), desc(schema.weekPlans.createdAt))
|
||||
.limit(8);
|
||||
|
||||
const result = [];
|
||||
@@ -50,6 +50,18 @@ export async function planningRoutes(app: FastifyInstance) {
|
||||
const input = parse(generateWeekPlanInputSchema, req.body);
|
||||
const householdId = await requireActiveHousehold(app.db, req.userId);
|
||||
|
||||
// "Planera om veckan" ersätter helt: ta bort ev. tidigare plan(er) för samma
|
||||
// vecka (kaskad tar entries) så vi aldrig samlar dubbletter och alltid visar
|
||||
// den nygenererade planen. Nytt plan-id ger dessutom ny variation (se workern).
|
||||
await app.db
|
||||
.delete(schema.weekPlans)
|
||||
.where(
|
||||
and(
|
||||
eq(schema.weekPlans.householdId, householdId),
|
||||
eq(schema.weekPlans.weekStartDate, input.weekStartDate),
|
||||
),
|
||||
);
|
||||
|
||||
const [plan] = await app.db
|
||||
.insert(schema.weekPlans)
|
||||
.values({
|
||||
@@ -89,6 +101,26 @@ export async function planningRoutes(app: FastifyInstance) {
|
||||
const input = parse(updatePlanEntryInputSchema, req.body);
|
||||
const updates: Record<string, unknown> = { ...input };
|
||||
|
||||
// Byt rätt: när ett nytt recept väljs måste titeln (och portioner) följa med,
|
||||
// annars visar kalendern kvar den gamla rätten trots att recipeId har bytts.
|
||||
if (typeof input.recipeId === "string") {
|
||||
const [recipe] = await app.db
|
||||
.select({
|
||||
id: schema.recipes.id,
|
||||
titleSv: schema.recipes.titleSv,
|
||||
portions: schema.recipes.portions,
|
||||
})
|
||||
.from(schema.recipes)
|
||||
.where(and(eq(schema.recipes.id, input.recipeId), eq(schema.recipes.status, "published")))
|
||||
.limit(1);
|
||||
if (!recipe) throw errors.notFound("Receptet finns inte.");
|
||||
updates.titleSv = recipe.titleSv;
|
||||
updates.mealBoxId = null;
|
||||
if (input.portions == null) updates.portions = recipe.portions ?? 2;
|
||||
updates.status = input.status ?? "planned";
|
||||
updates.rescheduleReasonSv = null;
|
||||
}
|
||||
|
||||
// Dynamisk omplanering med förklaring (spec §25)
|
||||
if (input.status === "skipped") {
|
||||
const [entry] = await app.db
|
||||
|
||||
Reference in New Issue
Block a user