From 877051cfafe725f159d580634fd103c8002dc438 Mon Sep 17 00:00:00 2001 From: Piotr Oleszczyk Date: Tue, 3 Mar 2026 20:01:39 +0100 Subject: [PATCH] feat(routines): add actives and recent usage tracking to product context --- backend/innercontext/api/routines.py | 30 +++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/backend/innercontext/api/routines.py b/backend/innercontext/api/routines.py index 290a252..32ec462 100644 --- a/backend/innercontext/api/routines.py +++ b/backend/innercontext/api/routines.py @@ -268,7 +268,11 @@ def _build_recent_history(session: Session) -> str: return "\n".join(lines) + "\n" -def _build_products_context(session: Session, time_filter: Optional[str] = None) -> str: +def _build_products_context( + session: Session, + time_filter: Optional[str] = None, + reference_date: Optional[date] = None, +) -> str: stmt = select(Product).where(col(Product.is_tool).is_(False)) products = session.exec(stmt).all() product_ids = [p.id for p in products] @@ -285,6 +289,19 @@ def _build_products_context(session: Session, time_filter: Optional[str] = None) for inv in inventory_rows: inv_by_product.setdefault(inv.product_id, []).append(inv) + recent_usage_counts: dict[UUID, int] = {} + if reference_date is not None: + cutoff = reference_date - timedelta(days=7) + recent_usage = session.exec( + select(RoutineStep.product_id) + .join(Routine) + .where(col(Routine.routine_date) > cutoff) + .where(col(Routine.routine_date) <= reference_date) + ).all() + for pid in recent_usage: + if pid: + recent_usage_counts[pid] = recent_usage_counts.get(pid, 0) + 1 + lines = ["DOSTĘPNE PRODUKTY:"] for p in products: if p.is_medication and not _is_minoxidil_product(p): @@ -298,6 +315,9 @@ def _build_products_context(session: Session, time_filter: Optional[str] = None) f" category={ctx.get('category', '')} recommended_time={ctx.get('recommended_time', '')}" f" targets={ctx.get('targets', [])}" ) + if "actives" in ctx: + entry += f" actives={ctx['actives']}" + active_inventory = [inv for inv in p.inventory if inv.finished_at is None] open_inventory = [inv for inv in active_inventory if inv.is_opened] sealed_inventory = [inv for inv in active_inventory if not inv.is_opened] @@ -335,6 +355,8 @@ def _build_products_context(session: Session, time_filter: Optional[str] = None) entry += f" min_interval_hours={ctx['min_interval_hours']}" if ctx.get("max_frequency_per_week"): entry += f" max_frequency_per_week={ctx['max_frequency_per_week']}" + usage_count = recent_usage_counts.get(p.id, 0) + entry += f" used_in_last_7_days={usage_count}" lines.append(entry) return "\n".join(lines) + "\n" @@ -476,7 +498,9 @@ def suggest_routine( grooming_ctx = _build_grooming_context(session, weekdays=[weekday]) history_ctx = _build_recent_history(session) day_ctx = _build_day_context(data.leaving_home) - products_ctx = _build_products_context(session, time_filter=data.part_of_day.value) + products_ctx = _build_products_context( + session, time_filter=data.part_of_day.value, reference_date=data.routine_date + ) objectives_ctx = _build_objectives_context(data.include_minoxidil_beard) notes_line = f"\nKONTEKST OD UŻYTKOWNIKA: {data.notes}\n" if data.notes else "" @@ -545,7 +569,7 @@ def suggest_batch( skin_ctx = _build_skin_context(session) grooming_ctx = _build_grooming_context(session, weekdays=weekdays) history_ctx = _build_recent_history(session) - products_ctx = _build_products_context(session) + products_ctx = _build_products_context(session, reference_date=data.from_date) objectives_ctx = _build_objectives_context(data.include_minoxidil_beard) date_range_lines = []