Skip to main content

Gift & Giftstore

What it is​

Two related but distinct modules: giftstore is the product catalog (browsing, search, AI-powered collections, wishlists) that both event gift-registries and standalone gift orders draw from; gift is the order lifecycle for sending someone a curated physical gift box (wrap, items, delivery). Neither should be confused with the event gift types (Secret Santa, My Birthday — see Events & Event Types), which are a category of event rather than a product order.

Core concepts​

  • Giftstore products are organized by category, with both traditional filtering (gift-category/:categoryId/products) and AI-powered discovery — semantic search (search/products) and generated "collections" (collections/generate) backed by vector embeddings, the same pattern used by Vendors discovery.
  • Wishlist has a staged, two-phase commit: items added via wishlist/:ref/add-temporary land in a Redis-cached staging area (WISHLIST_TEMP_KEY:{userId}:wishlist-{ref}), not the database — nothing is persisted until wishlist/:ref/confirm ({ confirm: true }) writes the whole batch to the permanent wishlist at once. This lets a client build up a wishlist interactively (add, remove, reconsider) without committing partial state, and without a DB write per add/remove.
  • A gift order starts minimal and grows: POST /gift/orders only requires title and wrapId — everything else (items, recipient, delivery, theme) is attached afterward through separate PATCH calls, not a single large create payload.

How it works​

Building a gift order​

  1. POST /gift/orders — create with just a title and a wrap (GET /gift/wraps lists available wrap designs).
  2. PATCH /gift/orders/:id/items — add items to the box incrementally.
  3. PATCH /gift/orders/:id/recipient — set who it's going to.
  4. PATCH /gift/orders/:id/theme-title — adjust presentation.
  5. POST /gift/orders/:orderId/delivery-fee — calculate delivery cost once contents/recipient are known (fee depends on what's being shipped and to where, so it's computed on demand rather than upfront).
  6. PATCH /gift/orders/:id/payment — record payment info once the order is ready to finalize.
  7. PATCH /gift/orders/:id/status — move through the order lifecycle (OrderStatus: pending → ongoing/scheduled → delivered, or missed/rejected/cancelled).

DELETE /gift/orders/:id cancels; DELETE /gift/orders/:id/force is a distinct force-delete path — worth checking what state a normal cancel refuses to leave before reaching for the force variant.

Discovery (giftstore)​

  • GET /giftstore/products, GET /giftstore/products/:id, GET /giftstore/products/categories/:slug — standard catalog browsing.
  • GET /giftstore/search, GET /giftstore/search/products — search, with a query-result cache (POST /search/clear-cache to bust it).
  • POST /giftstore/collections/generate — AI-generated product collections (curated groupings, not manually assembled); also cached (POST /collections/clear-cache).
  • GET /giftstore/public/wishlist/event/:eventId/items — the public-facing view of an event's permanent wishlist (registry), distinct from a user's personal temporary/permanent wishlist above.

Key business rules & edge cases​

  • Temporary wishlist items are Redis-backed and therefore expire/evictable — don't treat an unconfirmed temporary wishlist as durable; if a client needs to guarantee an item survives a long gap between add and confirm, that's a product risk worth flagging, not just an implementation detail.
  • A gift order's minimal creation requirement (title + wrapId only) means a lot of the order's validity (has items, has a recipient, delivery is calculable) isn't enforced at creation time — check order completeness explicitly before assuming it's ready to progress past pending.
  • Vector-index maintenance endpoints (POST /giftstore/vector/index, /index-all, /index-bundles) are separate, manually-triggered operations — new products don't automatically become searchable via semantic search until indexed.

Gift orders: GET /v1/gift/wraps, POST /v1/gift/orders, GET /v1/gift/orders, GET /v1/gift/orders/{id}, PATCH /v1/gift/orders/{id}/items, PATCH /v1/gift/orders/{id}/status.

Giftstore: GET /v1/giftstore/products, GET /v1/giftstore/search, POST /v1/giftstore/wishlist/{wishlistReference}/add-temporary, POST /v1/giftstore/wishlist/{wishlistReference}/confirm.

Not yet in the generated OpenAPI spec.

  • src/modules/gift/gift.routes.ts, gift.controller.ts, gift.service.ts
  • src/modules/giftstore/giftstore.routes.ts, giftstore.controller.ts, giftstore.service.ts, giftstoreVector.service.ts
  • src/shared/enum/status.enum.ts — OrderStatus