| Ticket | Title | Estimate | Week | Dependencies | Assignee | Priority | Risk |
|---|---|---|---|---|---|---|---|
| LOY-001 | NestJS Scaffold | 10h | Wk1 | None | Dev1 | P0 | Low |
| LOY-002 | DB Models & Migrations | 14h | Wk1 | LOY-001 | Dev1 | P0 | Low |
| LOY-003 | PDI REST Client | 22h | Wk1 | LOY-001 | Dev2 | P0 | High |
| LOY-004 | Session State Machine | 10h | Wk1 | LOY-002 | Dev1 | P0 | Medium |
| LOY-005 | OAuth2 Token Mgmt | 12h | Wk1 | LOY-003 | Dev2 | P0 | Medium |
| LOY-006 | StoreLoyaltyConfig Admin | 6h | Wk1 | LOY-002 | Dev3 | P0 | Low |
| LOY-007 | Medusa Store Routes | 18h | Wk2 | LOY-003+004 | Dev1 | P0 | Medium |
| LOY-008 | Loyalty Identifier UI | 10h | Wk2 | LOY-007 | Dev3 | P0 | Medium |
| LOY-009 | Reward Selector UI | 10h | Wk2 | LOY-007 | Dev3 | P0 | Medium |
| LOY-010 | Points Display | 6h | Wk2 | LOY-008 | Dev3 | P0 | Low |
| LOY-011 | Checkout Integration | 18h | Wk2 | LOY-007+008 | Dev1 | P0 | High |
| LOY-012 | Cart Re-evaluation | 10h | Wk2 | LOY-009 | Dev2 | P0 | Medium |
| LOY-013 | Error Handling & Fallback | 10h | Wk2 | LOY-011 | Dev2 | P0 | High |
| LOY-014 | Finalization Flow | 12h | Wk3 | LOY-011 | Dev1 | P0 | High |
| LOY-015 | Unit Tests | 14h | Wk3 | LOY-014 | Dev2 | P0 | Low |
| LOY-016 | Integration Tests | 14h | Wk3 | LOY-014 | Dev1 | P0 | Medium |
| LOY-017 | E2E & Load Tests | 10h | Wk3 | LOY-016 | Dev3 | P0 | Medium |
| TOTAL | 206h | ||||||
| # | Task | Type | Hours |
|---|---|---|---|
| 1.1 | Initialize NestJS project with CLI nest new loyalty-service, configure TypeScript strict mode, add .prettierrc and .eslintrc | Setup | 1.0h |
| 1.2 | Docker & Docker Compose setup Dockerfile (multi-stage build), docker-compose.yml with PostgreSQL, Redis, service networking | Config | 1.5h |
| 1.3 | Nginx reverse proxy config nginx.conf route /loyalty/* to loyalty-service:3001, SSL termination, CORS headers | Config | 1.0h |
| 1.4 | Health check controller & module GET /loyalty/health returning status, timestamp, version. Readiness/liveness probes | Code | 0.5h |
| 1.5 | Environment configuration module ConfigModule with .env validation (Joi schema), .env.example with all required vars | Setup | 1.0h |
| 1.6 | Database connection & TypeORM setup TypeOrmModule.forRootAsync, PostgreSQL connection, migration CLI scripts | Setup | 1.5h |
| 1.7 | CI pipeline skeleton GitHub Actions workflow: lint, build, test, docker build. Branch protection rules | Setup | 1.0h |
| 1.8 | Smoke test & documentation Verify boot, health endpoint, Docker build, write README setup instructions | Test | 0.5h |
| 1.9 | Structured logging setup (Winston/Pino) Configure structured JSON logging with correlation IDs, log levels, and request tracing middleware | Config | 1.0h |
| 1.10 | Security hardening & rate limiting Helmet middleware, CORS policy, rate limiter on /loyalty/* endpoints, input sanitization | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 2.1 | StoreLoyaltyConfig entity TypeORM entity: id, store_id (UUID unique), loyalty_provider, participant_id, site_id, program_id, enabled, credentials (JSONB encrypted), timestamps | Code | 1.5h |
| 2.2 | LoyaltySession entity id, session_id (UUID unique), store_id, customer_id, cart_id, order_id, loyalty_id, status enum, pdi_sequence_id, rewards (JSONB), applied_rewards (JSONB), error_log (JSONB), timestamps | Code | 2.0h |
| 2.3 | LoyaltyTransaction entity id, session_id FK, transaction_type enum (get_rewards, finalize, cancel), request_payload (JSONB), response_payload (JSONB), pdi_response_code, latency_ms, timestamps | Code | 1.5h |
| 2.4 | Database migrations CreateStoreLoyaltyConfig, CreateLoyaltySession, CreateLoyaltyTransaction, indexes on store_id, session_id, status, created_at | Setup | 1.5h |
| 2.5 | Repository layer Custom repositories with query methods: findActiveSession, findByStoreId, findExpiredSessions, session status transition methods | Code | 1.5h |
| 2.6 | Seed data & fixtures Dev seed: 3 test stores with PDI config, 5 sample sessions in various states. Test fixtures for unit tests | Setup | 1.0h |
| 2.7 | Entity validation & constraints Class-validator decorators, DB-level constraints (CHECK status IN enum), unique indexes, cascade rules | Code | 1.0h |
| 2.8 | Unit tests for repositories Jest tests for all repository methods, mock TypeORM connection, test edge cases (duplicate store, invalid status transition) | Test | 1.5h |
| 2.9 | Schema review & documentation ER diagram, document all columns, review with team, check index coverage for expected queries | Review | 0.5h |
| 2.8 | Database seeding scripts Create dev/staging seed data for loyalty_sessions, rewards, point_balances with realistic test scenarios | Code | 1.0h |
| 2.9 | Query performance indexing Add composite indexes on frequently queried columns, EXPLAIN ANALYZE on critical queries | Config | 1.0h |
| Subtotal | 14.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 3.1 | HTTP module & Axios setup NestJS HttpModule.registerAsync with timeout (10s), retry config, base URL from env | Setup | 0.5h |
| 3.2 | PDI OAuth2 token service PdiAuthService: getToken() with cache, Base64 encoding of clientId:secret, B2B grant_type, token refresh before expiry (300s buffer) | Code | 2.0h |
| 3.3 | Request/Response DTOs TypeScript interfaces for all 8 endpoints: RequestHeader, GetRewardsRequest/Response, FinalizeRewardsRequest/Response, TransactionData, FuelPriceData, RewardActions, LoyaltyId, etc. | Code | 1.5h |
| 3.4 | PDI header builder Build required headers: participant-id, site-id, program-id, Authorization from StoreLoyaltyConfig + cached token | Code | 0.5h |
| 3.5 | Online status endpoint client POST /pdi-conexxus/online-status — check system availability, parse promptForLoyaltyFlag | Code | 0.5h |
| 3.6 | GetRewards endpoint client POST /pdi-conexxus/rewards/get — multi-step reward retrieval, handle loyaltySequenceId chaining, parse rewardActions (prepay/postpay/merchandise) | Code | 2.0h |
| 3.7 | FinalizeRewards endpoint client POST /pdi-conexxus/rewards/finalize — commit transaction, handle offline fallback to /finalize-offline | Code | 1.5h |
| 3.8 | Cancel & Status endpoint clients POST /rewards/cancel, /rewards/status, /redemption/cancel, /period/end — simpler payloads, handle 204 No Content | Code | 1.0h |
| 3.9 | Circuit breaker (opossum) CircuitBreakerService wrapping all PDI calls: 5 failures = open, 30s reset, half-open probe. Fallback returns cached rewards or graceful degradation | Code | 1.5h |
| 3.10 | Error classification & retry Classify PDI errors: transient (503, timeout) vs permanent (400, 401). Retry transient with exponential backoff (3 attempts, 1s/2s/4s) | Code | 1.0h |
| 3.11 | Request/response logging Structured logging: correlation ID, endpoint, latency, status, truncated payload. Redact sensitive fields (accessToken, credentials) | Code | 0.5h |
| 3.12 | Unit tests for PDI client Mock Axios responses for all 8 endpoints, test token caching/refresh, circuit breaker state transitions, error classification | Test | 2.0h |
| 3.13 | Integration test with PDI staging Hit actual PDI staging API with test credentials, verify real GetRewards → FinalizeRewards flow end-to-end | Test | 1.0h |
| 3.14 | Code review & security audit Review credential handling, token storage, header injection risks. Verify no secrets in logs. Peer review all DTOs against OpenAPI spec | Review | 0.5h |
| 3.10 | PDI client request/response logging Structured logging for all PDI API calls with redacted PII, latency tracking, correlation IDs | Code | 1.5h |
| 3.11 | Connection pooling & keep-alive config Configure HTTP agent connection pooling, keep-alive timeouts, DNS caching for PDI endpoints | Config | 1.0h |
| 3.12 | PDI sandbox environment setup Configure separate PDI sandbox credentials, environment switching, mock server for local dev | Setup | 1.5h |
| 3.13 | PDI response caching layer Redis-based response cache for idempotent PDI lookups, configurable TTL per endpoint, cache invalidation on mutations | Code | 1.0h |
| 3.14 | PDI client health monitoring Periodic health-check pings to PDI endpoints, circuit breaker status dashboard endpoint, uptime tracking | Code | 1.0h |
| Subtotal | 22.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 4.1 | Session status enum & transitions Define LoyaltySessionStatus enum (active, pending_finalization, finalized, failed, expired). Valid transition map with guard validation | Code | 1.0h |
| 4.2 | SessionService.createSession() Create new session: generate UUID, set active status, store loyalty_id, link to cart/customer, persist to DB | Code | 1.0h |
| 4.3 | SessionService.transitionState() Validate transition is allowed, update status + timestamp, log transition event. Throw on invalid transition | Code | 1.0h |
| 4.4 | Session expiry & cleanup Scheduled job (cron every 5 min): find active sessions older than 30 min, transition to expired. configurable TTL | Code | 1.0h |
| 4.5 | Session query endpoints GET /loyalty/session/:id — return session with rewards. GET /loyalty/sessions?storeId=X — list active sessions | Code | 0.5h |
| 4.6 | Rollback mechanism On failed finalization: transition to failed, log error, unlock any locked rewards via /rewards/cancel PDI call | Code | 1.0h |
| 4.7 | Unit tests for state machine Test all valid transitions, invalid transition rejection, expiry logic, rollback flow, concurrent transition handling | Test | 2.0h |
| 4.8 | State diagram documentation Mermaid state diagram, document all transitions with trigger events, add to microservice-design docs | Review | 0.5h |
| 4.8 | State transition audit logging Log all session state transitions with timestamps, trigger events, and actor context for debugging | Code | 1.0h |
| 4.9 | Concurrent session conflict resolution Handle race conditions when multiple requests modify same session, optimistic locking strategy | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 5.1 | Token cache service In-memory cache with TTL tracking. Store: accessToken, expiresAt (with 300s buffer), environment key | Code | 1.0h |
| 5.2 | Credential management Read clientId/secret from StoreLoyaltyConfig.credentials (encrypted JSONB). Base64 encode for Basic auth header | Code | 1.0h |
| 5.3 | Token request implementation POST to auth-connect.excentus.com/authservice/v2/accesstokens. Parse SUCCESS/FAILURE response. Handle B2B/B2C bizType | Code | 1.5h |
| 5.4 | Auto-refresh logic Check token validity before each PDI call. If expired or within 300s of expiry, request new token. Thread-safe with mutex/lock | Code | 1.0h |
| 5.5 | Multi-environment support Support simultaneous tokens for different environments (staging vs prod). Per-store token isolation | Config | 0.5h |
| 5.6 | Token error handling Handle 5000 (Invalid Credentials), 5001 (Invalid Grant Type), 5005 (System Error), 5009 (Invalid Biz Type). Alert on repeated auth failures | Code | 0.5h |
| 5.7 | Unit tests Test cache hit/miss, token refresh timing, concurrent requests, error scenarios, credential encoding | Test | 1.5h |
| 5.8 | Integration test with PDI auth Hit PDI staging auth endpoint with real Lula credentials, verify token response shape, test token reuse | Test | 0.5h |
| 5.9 | Security review Verify tokens not logged, credentials encrypted at rest, no token leakage in error responses | Review | 0.5h |
| 5.7 | Token encryption at rest Encrypt stored OAuth tokens using AES-256, secure key management via environment config | Code | 1.5h |
| 5.8 | Token refresh queue & dedup Implement Redis-based refresh queue to prevent thundering herd on token expiry, dedup concurrent refreshes | Code | 1.5h |
| 5.9 | OAuth flow monitoring dashboard Metrics for token grant success/failure rates, refresh latency, expiry warnings via structured logs | Code | 1.0h |
| Subtotal | 12.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 6.1 | Admin CRUD endpoints GET /admin/loyalty/stores — list configs. POST /admin/loyalty/stores/:id/config — create/update. DELETE disable config | Code | 1.0h |
| 6.2 | Validation & authorization Validate store exists in Medusa, admin-only auth middleware, input validation (participant_id format, required fields) | Code | 0.5h |
| 6.3 | Credential encryption Encrypt PDI credentials before storing in JSONB. Decrypt on read for PDI client. Use AES-256 with env-based key | Code | 0.5h |
| 6.4 | Config cache layer Cache StoreLoyaltyConfig per store_id in Redis (5 min TTL). Invalidate on update. Reduce DB reads for every loyalty request | Setup | 0.5h |
| 6.5 | Admin UI data contract TypeScript response DTOs (mask secrets in response), pagination support, filter by enabled/provider | Code | 0.5h |
| 6.6 | Unit tests Test CRUD operations, validation rejection, credential masking in responses, cache invalidation | Test | 0.5h |
| 6.7 | Seed production configs Prepare config templates for initial stores, document required PDI onboarding values per store | Config | 0.5h |
| 6.6 | Config validation & schema enforcement Joi/Zod schema validation for store loyalty config, prevent invalid configurations, migration path for schema changes | Code | 1.0h |
| 6.7 | Multi-store config inheritance Support default config with per-store overrides, config diff visualization in admin panel | Code | 1.0h |
| Subtotal | 6.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 7.1 | Route registration & middleware Register /store/loyalty/* routes in Medusa API. Add loyalty middleware: check store has loyalty enabled, inject config | Setup | 1.0h |
| 7.2 | POST /store/loyalty/session Create loyalty session: validate cart exists, check store config, call loyalty-service, return session ID | Code | 1.5h |
| 7.3 | GET /store/loyalty/session/:id Retrieve session status, rewards, applied rewards. Handle session not found, expired session | Code | 0.5h |
| 7.4 | POST /store/loyalty/rewards Fetch rewards for cart: map Medusa cart items to PDI TransactionData format, call GetRewards, parse reward actions | Code | 1.5h |
| 7.5 | POST /store/loyalty/apply Apply selected reward to cart: validate reward still valid, update cart with discount metadata, call GetRewards step 2 | Code | 1.5h |
| 7.6 | POST /store/loyalty/decline Decline specific rewards via /redemption/cancel. Informational only, update session state | Code | 0.5h |
| 7.7 | Cart-to-PDI data mapper Transform Medusa cart items → PDI TransactionDetailGroup (ItemLine, FuelLine, TenderInfo). Handle UPC/PLU codes, quantities, prices | Code | 1.5h |
| 7.8 | Event subscribers Subscribe to cart.updated, order.placed, order.cancelled. Trigger session re-evaluation, finalization, cancellation respectively | Code | 1.0h |
| 7.9 | Unit tests Mock loyalty-service HTTP calls, test all route handlers, cart mapping edge cases, event subscriber triggers | Test | 1.5h |
| 7.10 | Integration tests Full flow: create session → get rewards → apply → checkout → finalize. Test with mock loyalty-service | Test | 1.0h |
| 7.11 | API documentation Document all new store routes in OpenAPI format, add to apis.html reference | Review | 0.5h |
| 7.8 | Request validation middleware Validate all loyalty route inputs with Zod schemas, standardized error responses, field-level error messages | Code | 1.5h |
| 7.9 | API versioning strategy Implement /v1/loyalty/* prefix, version negotiation headers, deprecation warnings for old clients | Code | 1.0h |
| 7.10 | Medusa event bus integration Subscribe to cart.updated, order.placed events for reactive loyalty processing, event replay capability | Code | 1.5h |
| 7.11 | Route-level caching middleware Cache GET endpoints for points balance and reward catalog with ETag/If-None-Match support, stale-while-revalidate | Code | 1.0h |
| 7.12 | OpenAPI spec generation Auto-generate OpenAPI 3.0 spec from route decorators, Swagger UI at /loyalty/docs, schema validation tests | Code | 1.0h |
| Subtotal | 18.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 8.1 | LoyaltyIdentifier component scaffold React component with TypeScript props, Tailwind CSS, connect to Redux loyalty slice | Setup | 0.5h |
| 8.2 | Phone/email input form Controlled input with format validation (phone: 10 digits, email: regex). Auto-format phone as user types | Code | 1.0h |
| 8.3 | Loyalty ID submission flow Call POST /store/loyalty/session with identifier. Show loading state, handle success (session created) and error (invalid ID) | Code | 2.0h |
| 8.4 | Member validation display Show loyalty ID valid/invalid status from PDI response. Display member name/points if returned in customerMessageData | Code | 1.0h |
| 8.5 | Entry method selector Toggle between manual entry, barcode scan (camera), phone entry. Maps to PDI entryMethod enum | Code | 1.0h |
| 8.6 | Error states & retry UI Network error, invalid ID, system offline states. Retry button, skip loyalty option | Code | 0.5h |
| 8.7 | Unit tests Render tests, form validation, API call mocking, error state rendering, accessibility checks (ARIA labels) | Test | 1.0h |
| 8.8 | Storybook stories Stories for all states: empty, loading, valid member, invalid ID, error, offline | Test | 0.5h |
| 8.9 | UX review Review with design team, verify mobile responsiveness, animation timing, focus management | Review | 0.5h |
| 8.7 | Phone number input with validation International phone format support, real-time validation feedback, country code auto-detect from store locale | Code | 1.0h |
| 8.8 | Loyalty ID persistence & autofill Remember returning customer loyalty IDs via secure cookie, autofill on return visits with opt-out | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 9.1 | RewardSelector component scaffold React component, TypeScript interfaces for RewardAction, connect to useLoyalty hook | Setup | 0.5h |
| 9.2 | Reward card rendering Display each reward: prompt text, discount method (amountOffPPU, percentOff), limit, fuel grade specific values | Code | 2.0h |
| 9.3 | Multi-reward selection logic Checkbox/toggle for optional rewards. instantRewardFlag=yes auto-selected. Track selected reward IDs | Code | 1.0h |
| 9.4 | Discount preview calculation Calculate estimated savings: rewardValue × expected quantity. Show per-grade breakdown for fuel rewards | Code | 1.0h |
| 9.5 | Apply/decline actions "Apply Rewards" button → POST /store/loyalty/apply. "Skip" → POST /store/loyalty/decline. Loading states | Code | 1.0h |
| 9.6 | Empty & loading states No rewards available message, skeleton loading cards, animation transitions | Code | 0.5h |
| 9.7 | Unit tests Test reward rendering variants, selection logic, apply/decline flows, empty state | Test | 1.0h |
| 9.8 | Storybook stories Fuel rewards, merchandise rewards, mixed rewards, no rewards, loading state | Test | 0.5h |
| 9.9 | Accessibility & UX review Keyboard navigation, screen reader support, color contrast for discount amounts | Review | 0.5h |
| 9.7 | Reward comparison tooltip Hover tooltip showing point cost vs monetary value comparison, best value indicator badge | Code | 1.0h |
| 9.8 | Reward category filtering Filter rewards by category (discounts, free items, upgrades), search within available rewards | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 10.1 | PointsDisplay component Compact widget component, receives loyalty status data from useLoyalty hook | Setup | 0.5h |
| 10.2 | Points balance rendering Format point count with thousands separator, show tier status if available, animated count-up | Code | 0.5h |
| 10.3 | Reward summary section Count of available rewards, total potential savings, "View Rewards" link to RewardSelector | Code | 0.5h |
| 10.4 | Account status call Call POST /pdi-conexxus/rewards/status (summary) on component mount. Cache result for session duration | Code | 1.0h |
| 10.5 | Responsive layout variants Full-width (checkout page), compact (header widget), tooltip (hover card) | Code | 0.5h |
| 10.6 | Unit tests Render with various point balances, loading state, error state, format number display | Test | 0.5h |
| 10.7 | Storybook + review Stories for all variants, visual regression testing, design approval | Review | 0.5h |
| 10.5 | Points history timeline Expandable timeline showing recent point transactions, earned/redeemed breakdown with dates | Code | 1.0h |
| 10.6 | Points expiry warning banner Show notification when points are expiring within 30 days, include CTA to redeem before expiry | Code | 1.0h |
| Subtotal | 6.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 11.1 | CheckoutLoyalty wrapper component Insert loyalty flow into existing checkout page. Feature flag: only render if store has loyalty enabled | Setup | 0.5h |
| 11.2 | Pre-checkout loyalty validation Before payment: verify session active, rewards still valid (re-call GetRewards if stale), block checkout if session expired | Code | 2.0h |
| 11.3 | Cart total adjustment Apply reward discounts to cart display totals. Show original price, discount amount, new total. Sync with Medusa cart metadata | Code | 2.0h |
| 11.4 | Payment flow integration Pass loyalty discount info to Stripe/Finix payment flow. Ensure discount reflected in payment amount, not just display | Code | 1.5h |
| 11.5 | Session state transition at checkout Transition session: active → pending_finalization on "Place Order" click. Handle race conditions (double-click, timeout) | Code | 1.0h |
| 11.6 | Order confirmation loyalty data Display earned points, applied discounts on order confirmation page. Include in order confirmation email data | Code | 1.0h |
| 11.7 | Rollback on payment failure If payment fails after session transition: rollback to active, re-enable reward selection. Cancel PDI transaction if needed | Code | 1.0h |
| 11.8 | Unit tests Test full checkout flow with loyalty, payment failure rollback, expired session handling, feature flag off | Test | 1.5h |
| 11.9 | E2E flow test Cypress: identify → select rewards → checkout → verify order has loyalty data → verify session finalized | Test | 1.0h |
| 11.10 | Code review — critical path Peer review: payment integration, race conditions, rollback logic. Security review of discount calculations | Review | 0.5h |
| 11.8 | Split payment with loyalty points Support partial point redemption combined with card payment, real-time balance recalculation | Code | 1.5h |
| 11.9 | Checkout loyalty summary panel Dedicated summary showing points earned, points redeemed, net value, and tier progress from this order | Code | 1.0h |
| 11.10 | Order confirmation loyalty receipt Post-checkout loyalty receipt showing transaction ID, points delta, new balance, next tier threshold | Code | 1.5h |
| 11.11 | Checkout rollback compensation Saga-pattern rollback if payment fails after loyalty deduction, automatic point reversal with audit trail | Code | 1.0h |
| 11.12 | Checkout analytics event emission Emit structured analytics events for loyalty usage at checkout, conversion tracking, A/B test bucketing support | Code | 1.0h |
| Subtotal | 18.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 12.1 | Cart change detection Subscribe to cart Redux state changes: item add/remove/quantity change, coupon apply/remove | Setup | 0.5h |
| 12.2 | Debounced re-evaluation Debounce cart changes (500ms) before calling GetRewards again. Reuse existing cart debounce pattern from codebase | Code | 1.0h |
| 12.3 | Reward diff & update Compare new rewards with previous. Highlight changes (new reward available, reward no longer valid, value changed) | Code | 1.5h |
| 12.4 | Optimistic UI updates Show loading indicator on reward cards during re-evaluation. Preserve selection state if reward IDs unchanged | Code | 1.0h |
| 12.5 | Edge case handling Empty cart (clear rewards), cart below minimum threshold, reward quantity limit exceeded by cart changes | Code | 1.0h |
| 12.6 | Unit tests Test debounce timing, reward diff logic, selection preservation, empty cart handling | Test | 1.5h |
| 12.7 | Integration test Full flow: add item → rewards update → remove item → rewards change → verify UI reflects changes | Test | 1.0h |
| 12.8 | Performance review Verify no excessive API calls, debounce working correctly, no memory leaks in subscription cleanup | Review | 0.5h |
| 12.7 | Debounced re-evaluation on rapid changes Debounce cart recalculations (300ms) to prevent API flooding during rapid quantity changes | Code | 1.0h |
| 12.8 | Cart loyalty state persistence Persist loyalty selections in cart metadata across page refreshes, session recovery after timeout | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 13.1 | Error boundary component React ErrorBoundary wrapping all loyalty components. Catch render errors, show fallback UI | Setup | 0.5h |
| 13.2 | Circuit breaker UI feedback When PDI circuit is open: show "Loyalty temporarily unavailable" banner, hide reward selector, allow checkout without loyalty | Code | 1.0h |
| 13.3 | Graceful degradation modes Mode 1: Full (all features). Mode 2: Read-only (show cached rewards, no new requests). Mode 3: Disabled (hide all loyalty UI) | Code | 2.0h |
| 13.4 | Error categorization display User-friendly messages per error type: network error, invalid session, system maintenance, token expired. No technical jargon | Code | 0.5h |
| 13.5 | Retry mechanisms Auto-retry for transient errors (3 attempts with backoff). Manual retry button for persistent errors. Skip loyalty button always available | Code | 1.0h |
| 13.6 | Logging & telemetry Frontend error logging: capture component, error type, session ID, cart state. Send to observability pipeline | Code | 0.5h |
| 13.7 | Unit tests Test all degradation modes, error boundary triggering, circuit breaker states, retry countdown | Test | 1.5h |
| 13.8 | Chaos testing Simulate PDI outage mid-checkout, network timeout during reward selection, token expiry during session | Test | 0.5h |
| 13.9 | Error UX review Review error messages with product team, verify no data leakage in error states, test with screen readers | Review | 0.5h |
| 13.7 | User-facing error message mapping Map PDI error codes to friendly customer-facing messages, localization-ready error strings | Code | 1.0h |
| 13.8 | Degraded mode admin notification Alert store admins when loyalty service enters fallback mode, include recovery instructions and ETA | Code | 1.0h |
| Subtotal | 10.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 14.1 | Order.placed event subscriber Subscribe to Medusa order.placed event, extract loyalty session ID from order metadata | Setup | 0.5h |
| 14.2 | Build finalization payload Map Medusa order → PDI FinalizeRewardsRequest: full transactionData with all line items, fuel lines, promotions applied, tender info | Code | 2.0h |
| 14.3 | Call PDI /rewards/finalize POST finalization request, handle success (commit accruals), parse customerMessageData for receipt | Code | 1.0h |
| 14.4 | Session state finalization Transition session: pending_finalization → finalized. Store PDI response, clear temporary reward locks | Code | 0.5h |
| 14.5 | Failure handling & retry queue If finalization fails: log error, keep session in pending_finalization, enqueue for retry. Dead letter after 3 attempts | Code | 1.0h |
| 14.6 | Offline finalization fallback If PDI is unreachable: call /rewards/finalize-offline, store for reconciliation. Flag order for manual review | Code | 0.5h |
| 14.7 | Order cancellation handler On order.cancelled: call /rewards/cancel, transition session to failed, release locked rewards | Code | 0.5h |
| 14.8 | Unit tests Test finalization success/failure, retry queue, offline fallback, order cancellation flow | Test | 1.5h |
| 14.9 | Code review — money path Critical review: verify discount amounts match PDI response, no double-finalization, idempotency check | Review | 0.5h |
| 14.7 | Idempotency key management Generate and store idempotency keys for all finalization calls, prevent duplicate point awards on retries | Code | 1.5h |
| 14.8 | Post-finalization webhook dispatch Fire webhooks to external systems (CRM, analytics) after successful loyalty transaction completion | Code | 1.0h |
| 14.9 | Finalization receipt PDF generation Generate downloadable PDF receipt with loyalty transaction details, QR code for verification | Code | 1.5h |
| Subtotal | 12.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 15.1 | Test infrastructure setup Jest config for loyalty-service, mock factories, test database setup/teardown, coverage thresholds (80%+) | Setup | 1.0h |
| 15.2 | PdiAuthService tests Token caching, refresh timing, Base64 encoding, error responses, concurrent token requests | Test | 1.0h |
| 15.3 | PdiClientService tests All 8 endpoint mocks, request payload validation, response parsing, header construction | Test | 2.0h |
| 15.4 | CircuitBreakerService tests Open/closed/half-open transitions, failure counting, timeout handling, fallback invocation | Test | 1.0h |
| 15.5 | SessionService tests State machine transitions, session creation/expiry, concurrent access, rollback scenarios | Test | 1.5h |
| 15.6 | Cart-to-PDI mapper tests Medusa cart → TransactionData, edge cases (empty cart, mixed items, fuel + merchandise), currency handling | Test | 1.5h |
| 15.7 | Medusa route handler tests All store API routes, middleware authorization, input validation, error responses | Test | 1.5h |
| 15.8 | Frontend component tests React Testing Library: LoyaltyIdentifier, RewardSelector, PointsDisplay, CheckoutLoyalty, error states | Test | 1.5h |
| 15.9 | Mock fixtures & factories Reusable PDI response fixtures, Medusa cart/order factories, store config generators | Code | 0.5h |
| 15.10 | Coverage report & gaps Run coverage, identify untested paths, add missing edge case tests. Target: 80%+ line coverage | Review | 0.5h |
| 15.8 | Snapshot testing for API contracts Jest snapshot tests for all API request/response shapes, auto-detect breaking contract changes | Test | 1.0h |
| 15.9 | Edge case & boundary tests Test zero-point redemption, max-int overflow, expired sessions, concurrent modifications, Unicode in names | Test | 1.0h |
| Subtotal | 14.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 16.1 | Test environment setup Docker Compose test stack: loyalty-service, PostgreSQL, Redis, mock PDI server (WireMock/MSW) | Setup | 1.5h |
| 16.2 | PDI mock server Mock all 8 PDI endpoints with realistic responses, configurable delays, error injection, stateful sequences | Code | 1.5h |
| 16.3 | Auth flow integration test Full OAuth2 flow: get token → cache → reuse → refresh on expiry → verify header propagation | Test | 1.0h |
| 16.4 | GetRewards flow test Supertest: create session → GetRewards step 1 (fuel prices) → GetRewards step 2 (with transaction data) → verify rewards | Test | 1.5h |
| 16.5 | Finalization flow test Full chain: session → rewards → apply → checkout event → finalize → verify session finalized in DB | Test | 1.5h |
| 16.6 | Error & fallback flow tests PDI timeout → circuit breaker opens → graceful degradation → circuit half-open → recovery | Test | 1.0h |
| 16.7 | Multi-store isolation test Two stores (PDI + Par Retail): verify requests route correctly, no cross-contamination, config isolation | Test | 1.0h |
| 16.8 | Database state verification After each flow: verify session status, transaction log entries, loyalty config state in PostgreSQL | Test | 1.0h |
| 16.9 | API contract tests Validate all request/response shapes match PDI OpenAPI spec v1.1. Schema validation with Ajv | Test | 0.5h |
| 16.10 | CI pipeline integration Add integration test stage to GitHub Actions, Docker Compose up/test/down, fail build on test failure | Setup | 0.5h |
| 16.11 | Test report & review Generate HTML test report, document known limitations, review flaky test mitigation | Review | 0.5h |
| 16.8 | Cross-service integration suite Test loyalty-service ↔ Medusa ↔ Next.js full round-trip flows with Docker Compose test environment | Test | 1.0h |
| 16.9 | PDI sandbox integration tests Validate all 8 PDI endpoints against sandbox, verify request signing, response parsing, error handling | Test | 1.0h |
| Subtotal | 14.0h |
| # | Task | Type | Hours |
|---|---|---|---|
| 17.1 | Cypress/Playwright E2E setup E2E test framework config, custom commands for loyalty flows, test data seeding | Setup | 1.0h |
| 17.2 | Happy path E2E test Full user flow: browse → add to cart → enter loyalty ID → view rewards → select reward → checkout → order confirmation with loyalty data | Test | 2.0h |
| 17.3 | Error path E2E tests Invalid loyalty ID, expired session, PDI offline during checkout, network interruption scenarios | Test | 1.0h |
| 17.4 | Feature flag E2E test Store without loyalty: verify no loyalty UI. Store with loyalty: verify full flow. Toggle mid-session behavior | Test | 0.5h |
| 17.5 | k6 load test scripts Load test: 50 concurrent users, GetRewards endpoint (most expensive). Measure p50/p95/p99 latency, error rate | Code | 1.0h |
| 17.6 | Load test execution Run against staging: ramp up 10→50→100 users over 10 min. Capture metrics, identify bottlenecks, verify circuit breaker under load | Test | 1.0h |
| 17.7 | Performance baseline Document baseline metrics: API latency, DB query times, memory usage. Set alerting thresholds | Test | 0.5h |
| 17.8 | Accessibility audit axe-core automated scan on all loyalty components. Verify WCAG 2.1 AA compliance. Fix critical violations | Test | 0.5h |
| 17.9 | Test summary & sign-off Compile all test results, create go/no-go recommendation, document known issues and workarounds | Review | 0.5h |
| 17.7 | Chaos engineering scenarios Test PDI timeout, DB connection loss, Redis failover, network partition recovery using tc/toxiproxy | Test | 1.0h |
| 17.8 | Performance baseline documentation Document p50/p95/p99 latencies, throughput limits, resource utilization under load, capacity planning | Test | 1.0h |
| Subtotal | 10.0h |