diff --git a/apps/api/src/routes/recommendations.ts b/apps/api/src/routes/recommendations.ts index 7efde05..b78e1df 100644 --- a/apps/api/src/routes/recommendations.ts +++ b/apps/api/src/routes/recommendations.ts @@ -330,10 +330,19 @@ export async function recommendationRoutes(app: FastifyInstance) { // --- 8. Tolka "jag är sugen på" (spec §19) --- const craving = q.craving ? parseCraving(q.craving) : null; + // Uttrycklig avsikt: användaren har valt en högtid, en tagg (t.ex. Baka) + // eller sökt på namn. Då ska hushållets vardags-tidsgräns INTE hårt gömma + // maten de faktiskt bett om (spec §28) – en kräftskiva eller ett bak tar + // tid. Tiden blir mjuk rankning i stället för diskvalificerande filter. + // En uttrycklig tidsgräns i förfrågan (q.maxMinutes) respekteras alltid. + const hasExplicitIntent = !!(q.holiday || q.tag || q.search); + const ctx: RecommendationContext = { mealType: q.mealType, persons: q.persons ?? (members.length ? members.length : 1), - maxMinutes: q.maxMinutes ?? myPrefs?.maxCookingMinutesWeekday ?? undefined, + maxMinutes: + q.maxMinutes ?? + (hasExplicitIntent ? undefined : (myPrefs?.maxCookingMinutesWeekday ?? undefined)), maxCostMinorPerPortion: q.maxCostMinorPerPortion, remainingProteinG: Math.max(0, daySummary.remaining.proteinG), remainingKcal: Math.max(0, daySummary.remaining.kcal), diff --git a/packages/recommendation-engine/test/engine.test.ts b/packages/recommendation-engine/test/engine.test.ts index b200529..2e60474 100644 --- a/packages/recommendation-engine/test/engine.test.ts +++ b/packages/recommendation-engine/test/engine.test.ts @@ -113,6 +113,16 @@ describe("poängsättning (spec §18)", () => { expect(ranked).toHaveLength(0); }); + it("utan tidsgräns behålls långsamma recept (t.ex. vid uttrycklig högtid/bak)", () => { + // Fixen: när användaren uttryckligen valt en högtid/tagg/sök sätter + // endpointen maxMinutes=undefined, så kräftskiva och bak inte gömms av + // vardagens tidsgräns. Långsamma recept ska då rankas – inte försvinna. + const slow = candidate({ recipeId: "slow", totalTimeMinutes: 90 }); + const ranked = rankAll([slow], { ...ctx, maxMinutes: undefined }); + expect(ranked).toHaveLength(1); + expect(ranked[0]!.recipeId).toBe("slow"); + }); + it("nyligen lagat straffas (variation)", () => { const recent = scoreCandidate(candidate({ daysSinceLastCooked: 2 }), ctx); const old = scoreCandidate(candidate({ daysSinceLastCooked: 30 }), ctx);