Shop It Docs
Developer Resourcescare-package

Care Package Module Feature List

Feature surfaces, state models, business rules, and integration flows for care packages.

Care Package Module - Feature List

1. Feature Overview

Care Package is a service contract attached to a physical product purchase. A care package grants the buyer a set of features (pick_drop, repair, service, priority_support, diagnostics, on_site, parts_coverage, warranty_extension) for a fixed duration.

Each care package has a URL-safe slug auto-generated from its name (e.g., "Basic Care" → "basic-care"). Historical slugs are preserved in care_package_slug_history to support SEO-preserving URL redirects. An optional link to a shared seo record enables per-package meta title, description, Open Graph tags, Twitter card metadata, and JSON-LD structured data.

Supported product type: care_package (productKind on products table).

Purchase model: customer selects a care package + pricing tier for a specific cart item, then checks out normally. Payment success triggers subscription creation and activation.

Subscription lifecycle: pending_activationactiveexpired (or cancelled / suspended).

2. Route Ownership and Surfaces

SurfaceRoute prefixOwnerSwagger tag
Customer eligibility API/api/care-packagesCarePackageCustomerControllerCare Packages (Mobile)
Mobile-composed/api/mobile/care-packagesMobileModule via CarePackageCustomerModulesame
Customer cart API/api/cart/items/:cartItemId/care-packageCarePackageCartControllerCart (Mobile)
Mobile-composed cart/api/mobile/cart/items/:cartItemId/care-packagesamesame
Customer subscription API/api/me/care-packagesCarePackageSubscriptionCustomerControllerCare Package Subscriptions (Mobile)
Mobile-composed subscription/api/mobile/me/care-packagessamesame
Customer redemption API/api/me/care-packages/:subscriptionId/requestsCarePackageRedemptionCustomerControllerCare Package Redemptions (Mobile)
Mobile-composed redemption/api/mobile/me/care-packages/:subscriptionId/requestssamesame
Admin packages API/api/admin/care-packagesCarePackageAdminControllerCare Packages (Admin)
Admin subscriptions API/api/admin/care-package-subscriptionsCarePackageSubscriptionsAdminControllerCare Package Subscriptions (Admin)
Admin redemptions API/api/admin/care-package-redemptionsCarePackageRedemptionAdminControllerCare Package Redemptions (Admin)

3. Admin Feature Matrix

Admin Care Packages

CapabilityEndpointPermission
List packagesGET /api/admin/care-packagesCarePackages_READ
Create packagePOST /api/admin/care-packagesCarePackages_CREATE
Get package detailGET /api/admin/care-packages/:idCarePackages_READ
Update packagePUT /api/admin/care-packages/:idCarePackages_UPDATE
Delete packageDELETE /api/admin/care-packages/:idCarePackages_DELETE
Duplicate packagePOST /api/admin/care-packages/:id/duplicateCarePackages_CREATE
Get matching productsGET /api/admin/care-packages/:id/matching-productsCarePackages_READ
Bulk upsert featuresPUT /api/admin/care-packages/:id/featuresCarePackages_UPDATE
Replace eligibility rulesPUT /api/admin/care-packages/:id/eligibility-rulesCarePackages_UPDATE
Bulk upsert pricing tiersPUT /api/admin/care-packages/:id/pricing-tiersCarePackages_UPDATE
Get notification scheduleGET /api/admin/care-packages/notification-scheduleCarePackages_READ
Upsert notification schedulePUT /api/admin/care-packages/notification-scheduleCarePackages_UPDATE
Upsert per-package notification schedulePUT /api/admin/care-packages/:id/notification-scheduleCarePackages_UPDATE

Admin Subscriptions

CapabilityEndpointPermission
List subscriptionsGET /api/admin/care-package-subscriptionsCarePackageSubscriptions_READ
Get subscription detailGET /api/admin/care-package-subscriptions/:idCarePackageSubscriptions_READ
Suspend subscriptionPOST /api/admin/care-package-subscriptions/:id/suspendCarePackageSubscriptions_UPDATE
Unsuspend subscriptionPOST /api/admin/care-package-subscriptions/:id/unsuspendCarePackageSubscriptions_UPDATE
Manual activatePOST /api/admin/care-package-subscriptions/:id/activateCarePackageSubscriptions_UPDATE

Admin Redemptions

CapabilityEndpointPermission
List redemption requestsGET /api/admin/care-package-redemptionsCarePackageRedemptions_READ
Get redemption requestGET /api/admin/care-package-redemptions/:idCarePackageRedemptions_READ
Update redemption statusPUT /api/admin/care-package-redemptions/:id/statusCarePackageRedemptions_UPDATE

4. Customer/Mobile Feature Matrix

CapabilityEndpointAuthNotes
List available care packagesGET /api/mobile/care-packages/availablePublicfiltered by product kind eligibility rules
Add care package to cart itemPOST /api/mobile/cart/items/:cartItemId/care-packageJWT1 per cart item; validates product eligibility and tier active
Remove care package from cart itemDELETE /api/mobile/cart/items/:cartItemId/care-packageJWTno-op if not attached
List my subscriptionsGET /api/mobile/me/care-packagesJWTfilterable by status; paginated
Get my subscription detailGET /api/mobile/me/care-packages/:idJWTincludes feature slots + usage + remainingDays
Raise redemption requestPOST /api/mobile/me/care-packages/:subscriptionId/requestsJWTvalidates active sub, quota
List redemption requestsGET /api/mobile/me/care-packages/:subscriptionId/requestsJWTpaginated
Get redemption requestGET /api/mobile/me/care-packages/:subscriptionId/requests/:requestIdJWT
Cancel redemption requestPOST /api/mobile/me/care-packages/:subscriptionId/requests/:requestId/cancelJWTonly if pending

5. Key Business Rules

  • Eligibility is defined per care package via care_package_eligibility_rules. Rules use a dimension (category, subcategory, brand, brand_series, product, or price_range) and a mode (include/exclude).
  • One care package per cart item — cartCarePackageItems has unique index on (cart_item_id) — one per cart item.
  • carePackageSnapshot and pricingSnapshot are written at subscription creation and are immutable after that point. They capture the care package definition and pricing tier at purchase time.
  • Subscription activation is triggered by the BullMQ job care_package.activate_subscription dispatched on order payment success. See subscription-lifecycle.mdx.
  • Feature quota enforcement: care_package_feature_usage tracks usedCount per (subscriptionId, featureType). Raise-time check compares usedCount against usageCount in the snapshot.
  • isUnlimited = true features skip quota checks entirely.
  • Redemption status transitions are strictly gated — see redemption.mdx for VALID_STATUS_TRANSITIONS table.
  • suspend requires status = "active". unsuspend requires status = "suspended". manualActivate requires status = "pending_activation".

6. Subscription Status State Machine

pending_activation
       │  ← order.payment_success (BullMQ activate job)

     active ──────────────────────────────► expired  (daily sweep OR expiryDate ≤ today)
       │                                      ▲
       │  ← admin suspend                     │ unsuspend when expiryDate past
       ▼                                      │
   suspended ─────────── unsuspend ──────── active

       │  ← order cancel / admin cancel job

   cancelled

   (also: any active/pending → cancelled via care_package.cancel_subscription job)

Full state machine detail: subscription-lifecycle.mdx.

7. Redemption Request State Machine

pending → accepted → in_progress → completed
pending → in_progress → completed
pending → in_progress → rejected
pending → rejected
accepted → completed
cancelled  (terminal, customer-initiated from pending)

Full state machine detail: redemption.mdx.

8. Error UX Mapping

errorCodeTypical HTTPUX action
CARE_PACKAGE_NOT_FOUND404Item not available; refresh care package list
CARE_PACKAGE_INACTIVE400Package no longer available; remove from cart
CARE_PACKAGE_PRICING_TIER_NOT_FOUND404Tier not available; re-select tier
CARE_PACKAGE_PRICING_TIER_INACTIVE400Tier no longer offered; re-select tier
CARE_PACKAGE_ELIGIBILITY_RULE_INVALID_TARGET400Admin input validation error
CARE_PACKAGE_ELIGIBILITY_RULE_PRICE_RANGE_INVALID400Admin input validation error
CARE_PACKAGE_NOTIFICATION_SCHEDULE_DUPLICATE409Admin: duplicate days-before-expiry entry
CARE_PACKAGE_DELETE_HAS_ACTIVE_SUBSCRIPTIONS409Cannot delete package with active subscribers
CARE_PACKAGE_CART_ITEM_NOT_FOUND404Cart item not found
CARE_PACKAGE_CART_ITEM_ALREADY_HAS_PACKAGE409Cart item already has a care package; remove first
CARE_PACKAGE_NOT_ELIGIBLE_FOR_PRODUCT400Selected package does not apply to this product; re-select from available packages
CARE_PACKAGE_CART_PACKAGE_NO_LONGER_AVAILABLE400Package deactivated; clear and re-add
CARE_PACKAGE_CART_PRICING_TIER_NO_LONGER_ACTIVE400Tier deactivated; re-select
CARE_PACKAGE_SUBSCRIPTION_NOT_FOUND404Subscription not found (also used for ownership mismatch — no disclosure)
CARE_PACKAGE_SUBSCRIPTION_NOT_ACTIVE400Subscription must be active to raise redemption request
CARE_PACKAGE_SUBSCRIPTION_ALREADY_ACTIVE400Admin: cannot manually activate a non-pending_activation subscription
CARE_PACKAGE_SUBSCRIPTION_ACTIVATE_FAILED400Activation failed — invalid snapshot data
CARE_PACKAGE_SUBSCRIPTION_SUSPEND_INVALID_STATUS400Only active subscriptions can be suspended
CARE_PACKAGE_SUBSCRIPTION_UNSUSPEND_INVALID_STATUS400Only suspended subscriptions can be unsuspended
CARE_PACKAGE_REDEMPTION_NOT_FOUND404Redemption request not found
CARE_PACKAGE_REDEMPTION_NOT_OWNED403Redemption request does not belong to this customer
CARE_PACKAGE_REDEMPTION_FEATURE_NOT_ENABLED400Feature not enabled in this care package
CARE_PACKAGE_REDEMPTION_QUOTA_EXCEEDED400Usage quota reached for this feature
CARE_PACKAGE_REDEMPTION_INVALID_STATUS_TRANSITION400Admin: invalid status transition
CARE_PACKAGE_REDEMPTION_CANCEL_NOT_PENDING400Customer: only pending requests can be cancelled

9. Integration Flows

9.1 Care Package Purchase Flow

  1. Customer calls GET /api/mobile/care-packages/available to browse eligible care packages for a product.
  2. Guest customers may include { carePackage: { carePackageId, pricingTierId } } on the product line in POST /api/mobile/cart/guest/quote for read-only totals.
  3. After login, POST /api/mobile/cart/sync persists the same optional care package selection while replacing the authenticated cart from the guest/local snapshot.
  4. Authenticated customers with an existing cart item may also call POST /api/mobile/cart/items/:cartItemId/care-package with { carePackageId, pricingTierId }.
  5. Backend validates: cart item exists + belongs to customer when using the direct add endpoint, product is physical, care package is active, eligibility rules match the product, and tier is active. Writes cartCarePackageItems row with selected IDs and unitPrice.
  6. Customer proceeds to checkout (POST /api/mobile/orders/checkout). Order service reads cartCarePackageItems, creates order_item rows for each, and creates care_package_subscriptions rows with status = "pending_activation".
  7. On payment success, order.payment_success BullMQ job runs. Processor enqueues care_package.activate_subscription job per subscription.
  8. CarePackageProcessor.processActivation() sets status = "active", calculates startDate / expiryDate from pricingSnapshot.durationMonths, schedules 30d and 7d reminder jobs.

9.2 Redemption Flow

  1. Customer calls POST /api/mobile/me/care-packages/:subscriptionId/requests with { featureType, description, attachmentUrls? }.
  2. Backend validates: subscription is active, feature is enabled in snapshot, quota not exceeded.
  3. Admin calls PUT /api/admin/care-package-redemptions/:id/status with { status: "accepted" }.
  4. On accept: DB transaction increments care_package_feature_usage.usedCount and updates request status.
  5. Admin advances through status machine (in_progress, completed).

10. Release/QA Checklist

  • GET /api/mobile/care-packages/available returns only active packages matching product eligibility rules.
  • Adding a care package to a cart item enforces 1-per-item constraint.
  • Guest quote and login sync preserve selected care package add-ons.
  • Cart total includes care package prices; care package lines do not trigger shipping.
  • Checkout creates care_package_subscriptions rows with status = "pending_activation".
  • Payment success enqueues care_package.activate_subscription jobs.
  • Activation sets status = "active", calculates dates from pricingSnapshot, schedules reminders.
  • Expiry sweep runs daily (cron) and bulk-expires active subscriptions past expiryDate.
  • Customer GET /api/mobile/me/care-packages/:id returns remainingDays and feature slot usage.
  • Redemption raise validates active status, feature enabled, quota.
  • Admin accepted transition increments carePackageFeatureUsage.usedCount in a transaction.
  • suspend/unsuspend/manualActivate enforce correct status guards.
  • unsuspend restores to active if expiryDate future, expired if past.
  • Ownership disclosure: customer GET /me/care-packages/:id returns same 404 code for not-found and wrong-owner.