make_post_sell/docs/tickets/mps-11.md
russell@unturf.com 5d501652c2 feat: add gift card system for shops (MPS-10 through MPS-13)
Variable-amount gift cards purchasable with any payment method.
Code-based redemption at checkout (applied to cart like coupons).
Partial use across multiple purchases, never expire. Shop owners
control min/max amounts and can disable individual cards.

Models: GiftCard, GiftCardTransaction, CartGiftCard + migration.
Views: purchase page, cart apply/remove, shop admin manage/detail/toggle.
Templates: gift_card.j2, gift_card_manage.j2, gift_card_detail.j2.
Cart integration: gift cards deduct after coupons in all checkout paths.
Tests: 10 new unit tests covering model logic (677 total pass).
2026-03-07 15:38:40 -05:00

2.7 KiB

MPS-11: Gift Card System — Purchase Flow

Problem

Buyers need a way to purchase gift cards for a shop. The shop owner sets a min/max amount range, and the buyer picks any amount within that range using a slider. The buyer can optionally enter a recipient email address so the gift card code is delivered to someone else.

Solution

Gift card "product" page

Gift cards are not regular products — they are a shop-level feature. A shop with gift_card_enabled=True gets a /shop/{slug}/gift-card page.

The page contains:

  • Shop name and branding
  • Amount slider (range input) with min/max from shop settings
  • Manual amount text input (synced with slider for precise entry)
  • Optional "Gift to" email field
  • Optional gift message (short text, stored on the card)
  • "Add to Cart" button

Cart integration

Gift cards are added to the cart as a special line item. Since they have variable pricing and are not regular products, they need a different storage approach in json_cart:

Option A: Store gift card items in a separate json_gift_cards column on Cart. Format: [{"shop_id": "...", "amount_in_cents": 2500, "gift_email": "...", "gift_message": "..."}]

This keeps gift cards cleanly separated from product line items and avoids polluting the existing json_cart dictionary (which maps product UUIDs to quantities).

Checkout

When the cart contains gift card items:

  1. Gift card amounts are included in the cart total
  2. After successful payment (Stripe, PayPal, or crypto), generate a MpsGiftCard record for each gift card line item
  3. Generate the unique code (GC- prefix + 16 hex chars)
  4. If gift_email is provided, send the code to the recipient
  5. Always show the code to the purchaser in the order confirmation

Email delivery

When gift_email is set, send a simple email to the recipient containing:

  • Shop name
  • Gift card amount
  • The redemption code
  • Optional gift message
  • Link to the shop

The email is informational only — the code IS the value. No account required.

Files Changed

File Change
views/gift_card.py New: gift card page + add-to-cart handler
templates/gift_card.j2 New: gift card purchase page with slider
static/js/gift_card.js New: slider/input sync, amount formatting
static/css/common.css Gift card page styles (using tokens)
models/cart.py Add json_gift_cards column, gift card total methods
views/cart.py Include gift card totals in checkout flow
views/checkout.py Generate MpsGiftCard records after payment
routes.py Add /shop/{slug}/gift-card route
lib/email.py Gift card delivery email template
templates/shop.j2 "Gift Cards" link when enabled

Depends On

MPS-10 (models and migration).