🧺 Kitchen Inventory
Audience: User, Org Admin, Developer, Support Related: Shopping Lists · Household and External Shopping · Data Retention
Kitchen Inventory tracks organization-scoped household items by canonical identity, grocery department, storage location, and Have It state. Active-item uniqueness prevents duplicate logical inventory records while allowing archived items to be restored.
Inventory filters shopping workflows but does not replace the Shopping List lifecycle. Archive, recently deleted, restore, purge, permission, and dependency behavior are documented here.
This document describes the current Kitchen Inventory and grocery-department model for Blackcap Pi, plus the Shop a List behaviors that use it.
Product language
Use these names consistently in the UI and documentation:
| Name | Meaning |
|---|---|
| Shopping Lists | The saved list records created from recipes and/or manual items. |
| Edit Shopping List | The Admin composition page for recipes, multipliers, manual items, preview, save, and rebuild. |
| Shop a List | The Admin and Mobile execution experience for checking items off in the store. |
| Kitchen Inventory | The household inventory list that tracks whether an item is on hand. |
| Grocery Department | Where an item is found in the store, such as Dairy or Produce. |
| Storage Location | Where the item lives at home, such as Refrigerator, Freezer, Pantry, or Spices. |
Use On hand as the friendly state for inventory items and for shopping-list rows that Blackcap believes are already available at home.
Core concepts
Grocery department and storage location are intentionally separate.
| Concept | Example | Used for |
|---|---|---|
| Grocery department | Dairy | Shop a List grouping and in-store navigation. |
| Storage location | Refrigerator | Kitchen Inventory organization. |
| Canonical item | milk | Normalized matching across recipes, shopping rows, and inventory. |
| Shopping item | 1 cup milk | A row in a specific shopping list. |
| Inventory item | Milk, on hand in Refrigerator | Household availability tracking. |
| Purchased product | Organic Valley Whole Milk, 1 gal | Future barcode/product detail. |
Current implemented behavior
Shopping Lists
Shopping lists are organization-scoped saved records. Cards in the Admin UI use consumer-friendly smart names, recipe thumbnails, active/completed state, and icon-first actions.
Smart names use a friendly date and recipe summary, for example:
May 22, 2026 · Cheeseburger Pie +1 Recipe
If duplicate names are created for the same date/recipe combination, Blackcap appends a suffix such as -1 or -2.
Completed lists are hidden from Shop a List and Edit Shopping List selectors until they are reopened from Shopping Lists. A completed list cannot remain active; completing an active list clears the active-list state.
Meal Planner source behavior
Meal Planner can create shopping lists from selected planned days/slots or, when nothing is selected, from the current configured/working week.
Recipe-backed meal-plan entries contribute recipe ingredients through the existing shopping-list generation path, including the saved recipe multiplier. Manual meal items such as French fries, 2 salad kits, or Burger sauce are treated as ingredient-style shopping candidates. If a manual meal item is not canonical-linked, it remains reviewable the same way an unresolved recipe ingredient is reviewable.
Meal Planner does not directly manage Kitchen Inventory, On Hand state, grocery departments, barcode capture, or inventory intake. Those behaviors remain owned by Shopping Lists, Shop a List, Kitchen Inventory, and Database Admin canonical/department cleanup.
Edit Shopping List
Edit Shopping List is the Admin composition and repair page. It is not the checkoff surface.
It supports:
- selecting an editable, non-completed shopping list;
- changing recipe multipliers with fraction controls such as
¼,½,¾,1, and1 ½; - removing recipes from a list;
- adding and removing truly manual shopping items only;
- live ingredient preview grouped by Recipe, Department, or None;
- a collapsible Ingredient Preview panel;
- responsive recipe tiles when Ingredient Preview is collapsed;
- automatic focus on the manual item entry field;
- Enter/Tab to quickly create the next manual item entry;
- unsaved-change warnings when switching lists or navigating away;
- AJAX save/rebuild behavior without a full page refresh.
Data Admin, Org Admin, and System Admin users can also use Rebuild. Rebuild regenerates recipe-derived ingredients from the current list recipes, multipliers, and manual items. It is a safe repair action if generated ingredient rows ever drift from the list's durable inputs.
Shop a List
Shop a List is the execution experience for shopping.
Admin and Mobile Shop a List support:
- checking items on/off;
- grouping by Recipe, Department, or None;
- filtering by Kitchen Inventory status: All items, On hand, or Need to shop;
- adding manual shopping items in-place;
- undo after removing a manual item;
- completing the list.
Admin Shop a List also includes grocery department management and drag/drop assignment. Dragging an item into a department changes the item's current department and updates the canonical department mapping so future lists are grouped better.
Mobile Shop a List includes a long-press department reassignment flow. Long-press an ingredient to open a modal, view the current department, choose a new department, or add a new department and immediately assign the item to it.
Completing a list marks only checked items as on hand in Kitchen Inventory. Unchecked items are skipped.
Inventory behavior and scope
Kitchen Inventory tracks simple household availability. The current model is intentionally not quantity-based.
Implemented behavior:
- Admin and Mobile Kitchen Inventory pages;
- search/filter by storage location;
- On hand, Not on hand, and All filters;
- manual item add/edit flows;
- edit display name, canonical name, storage location, grocery department, and notes;
- mark an item not on hand or back on hand;
- delete/archive an item into Recently Deleted and restore it during retention;
- re-adding a matching canonical/display item in the same location reuses the existing row and marks it on hand;
- edit modals require Cancel or Save rather than closing from an accidental outside click.
Kitchen Inventory records are organization-scoped.
Department resolution order
When rendering or grouping a shopping item, Blackcap resolves grocery department in this order:
- Item-level department override.
- Current organization's canonical item department mapping.
- Platform/default canonical item department mapping.
Other / Uncategorized.
Department changes made through Admin drag/drop or Mobile long-press should improve future lists by updating the canonical item mapping.
Database Admin data-management views
Database Admin includes the following relevant resources:
- Grocery Departments — department list and ordering.
- Inventory Locations — storage locations used by Kitchen Inventory.
- Kitchen Inventory Items — organization-owned active and archived inventory records, including lifecycle status and the remembered pre-archive on-hand state.
- Shopping Lists — saved shopping-list headers.
- Shopping List Items — individual shopping rows and check state.
- Shopping List Item Sources — recipe/manual attribution for rows.
- Item Department & Storage Map — canonical item mapping to grocery department and default storage location.
The Item Department & Storage Map resource includes a Review Uncategorized workflow. It surfaces canonical items from recipes, shopping lists, and Kitchen Inventory that are missing a department or still map to Other / Uncategorized. A data admin can review one suggestion at a time and assign both grocery department and default Kitchen Inventory storage location.
For Kitchen Inventory Items, the Database detail drawer exposes a Lifecycle Status safe edit with Active / Restored and Archived / Recently Deleted choices. This is not a raw status-column update: Blackcap calls the Kitchen Inventory domain service, preserves active-organization scope, writes the normal audit events, forces archived items off hand, and restores the remembered on-hand state when an item is reactivated. The lifecycle field requires both Database Admin edit access and inventory.delete.
Future barcode/product capture
Barcode scanning should be additive, not required.
Recommended future flow:
- User taps Scan.
- Browser camera scanner reads the barcode.
- Server checks a platform-level product cache.
- If cache misses, server queries an external product lookup provider.
- If lookup fails or is slow, the user can manually enter the product.
- Product data attaches to the shopping item or inventory item.
The shopping and inventory flows must keep working even when barcode lookup is unavailable.
Long-term north star
The long-term value is inventory-aware shopping:
- Blackcap knows what is already in Kitchen Inventory.
- Shopping-list generation flags or filters items already on hand.
- Needed items can later be associated to purchasable products.
- A future grocery-provider handoff can send needed products to a cart.
- After purchase/delivery, Blackcap can update Kitchen Inventory from confirmed checked/purchased items.
Implementation guardrails
- Keep route handlers thin.
- Use blueprints and service/repository layers.
- Do not add direct SQL to route handlers.
- Keep household data organization-scoped.
- Product barcode cache may be platform-level.
- Barcode lookup must have a manual fallback.
- Mobile interactions must remain fast and touch-friendly.
- Avoid confirmation prompts for low-risk manual item removals; prefer undo toasts.
- For advanced Admin UI pages, preserve the successful scroll pattern: header panels can scroll fully away, primary panels fill the visible viewport, internal scrollbars remain fully visible, and panel/page scroll handoff stays smooth.
Logical uniqueness and Have It
Kitchen Inventory enforces one logical item per organization and normalized ingredient identity. Storage location is a mutable attribute, so Have It updates and moves the existing item rather than creating a second Pantry/Refrigerator/Freezer record. Migration 206 reconciles existing duplicate rows before adding the unique index.
Recently Deleted, restore, and retention
Authorized users can delete a Kitchen Inventory item from its Admin or Mobile tile with the compact 🗑️ action. The user-facing action archives the item rather than immediately hard-deleting it.
Archived items:
- disappear from active On hand, Not on hand, and All active views;
- stop counting as currently on hand;
- do not satisfy shopping-list
Have Itchecks; - retain organization, canonical identity, location, department, notes, and safe audit context;
- appear in the authorized-only Recently deleted view;
- can be restored during the configured retention window.
The default retention window is 14 days. The Recently Deleted view shows the archived time, actor, storage location, expected purge time, and Restore action. Archived rows also appear immediately in Admin → Data Cleanup → Manual purge selected records, where an authorized administrator can preview and permanently purge a selected item early after the normal typed confirmation.
A later add/Have It operation for the same organization-scoped canonical identity restores and updates the archived row instead of creating a duplicate. This works with the migration 206 uniqueness rule.
Deletion/restoration requires inventory.delete. System Admin (in the selected organization context), Org Admin, and Data Admin have this permission by default. Operator and Contributor do not. Server-side permission and organization predicates are authoritative.
Migration 212_inventory_archive_retention.py adds the archive metadata and lookup/purge indexes. Permanent removal occurs only through the existing scheduled purge framework after the retention threshold.