- Problem Statement: eShop currently lacks a customer loyalty mechanism, resulting in lower repeat purchase rates and limited customer engagement. A loyalty program incentivizes users to return, increases average order value, and differentiates eShop from competitors.
- Target Users: Registered eShop customers (shoppers), marketing team (for campaigns), customer support (for issue resolution).
- Architecture Fit: Follow microservices principles; encapsulate loyalty logic in a dedicated service. Integrate with Ordering, Catalog, and Identity services via events and APIs.
- Service Boundaries: New
Loyalty.APImicroservice. Impacts Ordering.API (order completion), Identity.API (user profile), WebApp (UI integration), and potentially Catalog.API (reward-eligible products). - Data Ownership: Loyalty.API owns all loyalty program data (points, tiers, transactions, rewards). Ordering and Identity services reference loyalty data via APIs/events.
-
LOY-1: Award points for completed purchases
- Acceptance Criteria:
- Given a user completes an order,
- When the order is marked as paid,
- Then the user receives points based on order value and current promotions.
- Acceptance Criteria:
-
LOY-2: Support tiered membership (e.g., Bronze, Silver, Gold, Platinum)
- Acceptance Criteria:
- Given a user's cumulative points cross a tier threshold,
- When the next order is completed,
- Then the user's tier is upgraded and benefits are applied.
- Acceptance Criteria:
-
LOY-3: Allow users to view points balance, tier, and history
- Acceptance Criteria:
- Given a logged-in user,
- When they access the loyalty dashboard,
- Then they see current points, tier, and transaction history.
- Acceptance Criteria:
-
LOY-4: Enable points redemption for rewards (discounts, products, vouchers)
- Acceptance Criteria:
- Given a user has sufficient points,
- When they choose a reward to redeem,
- Then points are deducted and the reward is issued.
- Acceptance Criteria:
-
LOY-5: Admin management of loyalty rules, tiers, and promotions
- Acceptance Criteria:
- Given an admin user,
- When they update rules or promotions,
- Then changes are reflected in the loyalty program logic.
- Acceptance Criteria:
-
LOY-6: Notify users of tier upgrades and expiring points
- Acceptance Criteria:
- Given a user is upgraded or points are expiring soon,
- When the event occurs,
- Then the user receives an email or in-app notification.
- Acceptance Criteria:
- Security: Only authenticated users can access/modify their loyalty data. Admin APIs require elevated permissions. Prevent points fraud.
- Usability: Intuitive dashboard, clear tier progress, accessible on web/mobile.
- New Services:
Loyalty.API: RESTful microservice for all loyalty operations (points, tiers, rewards, admin management).
- Modified Services:
Ordering.API: PublishesOrderCompletedevents; consumes loyalty API for points awarding.Identity.API: Optionally displays loyalty status in user profile.WebApp: Integrates loyalty dashboard and redemption UI.
- Service Communication:
- Sync: WebApp/Identity calls Loyalty.API for user data.
- Async: Ordering.API emits
OrderCompletedevent; Loyalty.API subscribes and processes points.
- Data Flow:
- User completes order → Ordering.API emits event
- Loyalty.API processes event, updates points/tier
- User queries dashboard → WebApp fetches from Loyalty.API
- Redemption request → Loyalty.API validates, updates, issues reward
- New Tables/Collections (PostgreSQL):
LoyaltyAccounts(UserId PK, Points, Tier, LastActivity, CreatedAt)LoyaltyTransactions(Id PK, UserId FK, Type [Earn/Spend/Adjust], Points, OrderId, Timestamp, Description)LoyaltyTiers(TierId PK, Name, MinPoints, Benefits, Icon)LoyaltyRewards(RewardId PK, Name, PointsRequired, Type [Discount/Product/Voucher], Details, Active)LoyaltyRedemptions(RedemptionId PK, UserId FK, RewardId FK, PointsSpent, Status, CreatedAt, FulfilledAt)LoyaltyPromotions(PromotionId PK, Name, Multiplier, StartDate, EndDate, Active)- Utilize EnumToString conversion for enums in Context definition
- Data Relationships:
- 1:N from LoyaltyAccounts to LoyaltyTransactions and LoyaltyRedemptions
- LoyaltyTiers referenced by LoyaltyAccounts
- LoyaltyRewards referenced by LoyaltyRedemptions
- Migration Strategy:
- Add new schema via migration scripts. Backfill existing users with default loyalty accounts.
- Domain Events:
PointsAwarded,TierUpgraded,PointsRedeemed,PointsExpired,RewardIssued
- Integration Events:
OrderCompleted(from Ordering.API)UserRegistered(optional, for onboarding bonus)
- Event Handlers:
- Loyalty.API background worker for event processing (idempotent, retry on failure)
- Notification handler for user alerts
# Loyalty API Endpoints
GET /api/loyalty/account/{userId} # Get points, tier, history
POST /api/loyalty/redeem # Redeem points for reward
GET /api/loyalty/tiers # List available tiers
GET /api/loyalty/rewards # List available rewards
POST /api/loyalty/admin/rules # Update rules/promotions (admin)
POST /api/loyalty/admin/tier # Create/update tier (admin)
POST /api/loyalty/admin/reward # Create/update reward (admin)
# Event Subscription
POST /events/order-completed # (internal) handle order event
// Loyalty Domain
public class LoyaltyAccount {
public Guid UserId { get; set; }
public int Points { get; set; }
public string Tier { get; set; }
public DateTime LastActivity { get; set; }
public List<LoyaltyTransaction> Transactions { get; set; }
}
public class LoyaltyTransaction {
public Guid Id { get; set; }
public Guid UserId { get; set; }
public LoyaltyTransactionType Type { get; set; } // Earn, Spend, Adjust
public int Points { get; set; }
public Guid? OrderId { get; set; }
public DateTime Timestamp { get; set; }
public string Description { get; set; }
}
public enum LoyaltyTransactionType {
Earn,
Spend,
Adjust
}
public class LoyaltyTier {
public string Name { get; set; }
public int MinPoints { get; set; }
public string Benefits { get; set; }
public string Icon { get; set; }
}
public class LoyaltyReward {
public Guid RewardId { get; set; }
public string Name { get; set; }
public int PointsRequired { get; set; }
public LocaltyRewardType Type { get; set; } // Discount, Product, Voucher
public string Details { get; set; }
public bool Active { get; set; }
}
public enum LoyaltyRewardType {
Discount,
Product,
Voucher
}
public class LoyaltyRedemption {
public Guid RedemptionId { get; set; }
public Guid UserId { get; set; }
public Guid RewardId { get; set; }
public int PointsSpent { get; set; }
public RedemptionStatus Status { get; set; } // Pending, Fulfilled, Cancelled
public DateTime CreatedAt { get; set; }
public DateTime? FulfilledAt { get; set; }
}
public enum RedemptionStatus {
Pending,
Fulfilled,
Cancelled
}
// Interfaces
public interface ILoyaltyService {
LoyaltyAccount GetAccount(Guid userId);
void AwardPoints(Guid userId, int points, Guid? orderId = null);
void RedeemPoints(Guid userId, Guid rewardId);
void UpgradeTier(Guid userId);
IEnumerable<LoyaltyTier> GetTiers();
IEnumerable<LoyaltyReward> GetRewards();
}
public interface ILoyaltyAdminService {
void UpdateRules(LoyaltyRules rules);
void CreateOrUpdateTier(LoyaltyTier tier);
void CreateOrUpdateReward(LoyaltyReward reward);
}
// Business Logic (examples)
public void AwardPoints(Guid userId, int points, Guid? orderId = null) {
// 1. Fetch LoyaltyAccount
// 2. Add points, create LoyaltyTransaction
// 3. Check for tier upgrade
// 4. Emit PointsAwarded, TierUpgraded events if needed
}
public void RedeemPoints(Guid userId, Guid rewardId) {
// 1. Validate points balance
// 2. Deduct points, create LoyaltyRedemption
// 3. Issue reward, emit PointsRedeemed, RewardIssued events
}- Create Unit tests with xunit
- Scaffold Loyalty.API microservice
- Define database schema and migrations
- Implement basic CRUD for accounts, tiers, rewards
- Integrate with Ordering.API events
- Implement points awarding and tier logic
- Build user dashboard endpoints
- Implement admin management APIs
- Integrate with WebApp UI (dashboard, redemption)
- Add notifications for upgrades/expiring points
- End-to-end and integration testing
- Performance optimization and caching
- Security review and hardening
- Documentation and user guides
- Loyalty points calculation logic
- Tier upgrade logic
- Redemption validation
- Admin rule changes
- API endpoint tests (CRUD, dashboard, redemption)
- Event handler tests (order completed, points awarded)
- Database integration and migration tests
- User workflow: earn, view, redeem, upgrade
- Admin workflow: manage rules, tiers, rewards
- Performance and load tests
- Points awarded per day/week
- Tier upgrade rates
- Redemption rates and reward popularity
- API latency and error rates
- Structured logs for all loyalty transactions
- Correlation IDs for event-driven flows
- Security audit logs for admin actions
- Failed event processing
- Redemption failures
- Unusual points activity (fraud detection)
- Risk: Eventual consistency between Ordering and Loyalty (delayed points)
- Probability: Medium
- Impact: Medium
- Mitigation: Idempotent event handling, user messaging
- Risk: Points fraud or abuse
- Probability: Low
- Impact: High
- Mitigation: Validation, audit logs, anomaly detection
- Risk: Performance bottlenecks at scale
- Probability: Medium
- Impact: Medium
- Mitigation: Caching, async processing, DB indexing
- Risk: Low user adoption
- Mitigation: Marketing campaigns, onboarding bonuses
- Risk: Reward cost overruns
- Mitigation: Dynamic reward management, analytics
- Context: Where to implement loyalty logic
- Options Considered: Integrate into Ordering.API vs. new Loyalty.API
- Decision: New Loyalty.API microservice
- Rationale: Separation of concerns, scalability, future extensibility
- Consequences: Additional deployment, but better maintainability
- Context: How to trigger points for orders
- Options Considered: Synchronous API call vs. event subscription
- Decision: Subscribe to OrderCompleted events
- Rationale: Decouples services, resilient to failures
- Consequences: Eventual consistency, requires idempotency