Happy House - Ecommerce Docs
Developer ResourcesWishlist

Wishlist Module Overview

The products a customer has intentionally saved — idempotent save/remove, membership ids, and always-live product data.

Audience: Product owners, QA, frontend and backend developers Scope: The wishlist surface, its idempotency model, and what it deliberately does not do

Wishlist Module - Overview

1. What the module is

The wishlist remembers the products a customer has intentionally saved. Four customer routes: list, a membership id-set for heart icons, and idempotent save/remove keyed on the product.

It knows nothing about carts, checkout, orders, payments or promotions. It never reserves inventory and never snapshots a price — a saved item always shows what the product costs and whether it is in stock right now.

2. The four routes

RouteBehaviour
GET /api/mobile/wishlistlist, 4 filters, 4 sorts, paginated by default
GET /api/mobile/wishlist/product-idsmembership set for the heart icon, 30s cache
PUT /api/mobile/wishlist/products/:productIdidempotent save, 200 not 201
DELETE /api/mobile/wishlist/products/:productIdidempotent, never 404s

3. The rules that matter

  1. The unique constraint (customer_id, product_id) IS the idempotency guarantee. Save is one INSERT … ON CONFLICT DO NOTHING; there is no service-level duplicate check to forget.
  2. There is no soft delete, deliberately. A deleted_at would force the unique constraint to become partial, and re-adding a removed product would then need a read-modify-write with a race in the middle. Hard delete keeps the guarantee in the database.
  3. A product may only be saved while published or unlisted, but stays saved after it stops being. That asymmetry is the module's central behaviour — see the reason table on the features page.
  4. Saved items always show live product data. The wishlist never snapshots a price or stock level, so an item whose price changed yesterday shows today's price today.
  5. No new stock utility was built. The wishlist consumes InventoryAvailabilityService.getForProducts through ProductCardAssembler — the same batched seam cart uses, which is why the module is small.

Page guide

PageRead it for
Features and flowsActor journeys, the availability/reason table, edge cases
BackendSchema, idempotency model, cache, sort tiebreakers
APIThe four endpoints, DTOs and error codes