A NestJS-based microservice for aggregating hotel loyalty program transactions and providing analytics.
- Transaction Management: Create and manage loyalty point transactions (earn, redeem, transfer)
- Data Aggregation: Get aggregated data for points earned, current balances, and transfers
- Mock Data Support: Generate test data for development and testing
- RESTful API: Well-structured API endpoints with validation
- Database Integration: PostgreSQL with TypeORM
- Comprehensive Testing: Unit tests with Jest
The microservice is built with the following architecture:
- Transaction API: Handles CRUD operations for transactions
- Aggregation API: Provides analytical endpoints for data aggregation
- Database Layer: PostgreSQL with TypeORM for data persistence
- Business Logic: Service layer with transaction and aggregation logic
- EARN: Points earned through hotel stays
- REDEEM: Points redeemed for free nights
- TRANSFER: Points transferred to car rental partners
POST /api/v1/transactions
- Create a new transactionGET /api/v1/transactions
- Get all transactions with filteringGET /api/v1/transactions/:id
- Get transaction by IDGET /api/v1/transactions/user/:userId
- Get transactions for a specific userPOST /api/v1/transactions/mock/:userId
- Generate mock transactions for testing
GET /api/v1/aggregations/points-earned/:userId
- Get points earned by user for a periodGET /api/v1/aggregations/balance/:userId
- Get current balance for a userGET /api/v1/aggregations/transferred-points
- Get total points transferred to partnersGET /api/v1/aggregations/stats
- Get overall system statistics
- Docker and Docker Compose
- Node.js (v18 or higher) - for local development
- npm or yarn - for local development
-
Clone the repository
git clone <repository-url> cd hotel-loyalty-aggregator
-
Start services (simple setup)
make up-simple # or docker compose -f docker-compose.simple.yml up -d
-
Check if services are running
make health # or curl http://localhost:3000/api/v1/health
The application will be available at http://localhost:3000
For development with hot reload:
make dev
# or
docker compose -f docker-compose.dev.yml up -d
For production with Nginx load balancer:
make up
# or
docker compose up -d
All available commands:
make help # Show all available commands
make up-simple # Start services (simple setup)
make dev # Start in development mode
make down # Stop all services
make logs # Show logs
make restart # Restart services
make clean # Clean up Docker resources
make db-shell # Access database shell
-
Install dependencies
npm install
-
Start PostgreSQL (using Docker)
docker run --name postgres-local -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=loyalty_db -p 5432:5432 -d postgres:15-alpine
-
Environment Configuration
Create a
.env
file in the root directory:# Database Configuration DB_HOST=localhost DB_PORT=5432 DB_USERNAME=postgres DB_PASSWORD=postgres DB_NAME=loyalty_db # Application Configuration PORT=3000 NODE_ENV=development
-
Start the application
npm run start:dev # Development mode npm run start:prod # Production mode
npm test
npm run test:cov
npm run test:watch
- Service layer testing with mocked repositories
- Controller testing with mocked services
- Entity validation testing
- End-to-end API testing
- Database integration testing
- Performance testing for aggregation queries
The development follows TDD principles:
- Write failing tests first
- Implement minimal code to pass tests
- Refactor while keeping tests green
-
Start the application
make up-simple # or docker compose -f docker-compose.simple.yml up -d
-
Generate mock data
make mock-data # or curl -X POST http://localhost:3000/api/v1/transactions/mock/123e4567-e89b-12d3-a456-426614174000
-
Check application health
make health # or curl http://localhost:3000/api/v1/health
-
View running services
make ps # or docker compose -f docker-compose.simple.yml ps
-
Stop services
make down # or docker compose -f docker-compose.simple.yml down
curl -X POST http://localhost:3000/api/v1/transactions \
-H "Content-Type: application/json" \
-d '{
"userId": "123e4567-e89b-12d3-a456-426614174000",
"type": "earn",
"points": 100,
"description": "Hotel stay - 2 nights",
"hotelId": "hotel-123",
"bookingReference": "BK-2024-001"
}'
curl http://localhost:3000/api/v1/aggregations/balance/123e4567-e89b-12d3-a456-426614174000
curl "http://localhost:3000/api/v1/aggregations/points-earned/123e4567-e89b-12d3-a456-426614174000?startDate=2024-01-01&endDate=2024-12-31"
curl "http://localhost:3000/api/v1/aggregations/transferred-points?partnerId=car-rental-123&startDate=2024-01-01&endDate=2024-12-31"
curl http://localhost:3000/api/v1/aggregations/stats
# Start services
make up-simple # Simple setup (app + database)
make dev # Development mode with hot reload
make up # Full production setup with Nginx
# Monitor services
make logs # View all logs
make logs-app # View application logs only
make ps # Show running containers
make health # Check service health
# Database operations
make db-shell # Access database shell
make mock-data # Generate test data
# Cleanup
make down # Stop services
make clean # Remove all containers and volumes
- Indexes on frequently queried columns (userId, type, createdAt)
- Query optimization for aggregation operations
- Connection pooling for high-concurrent requests
- Redis for caching frequently accessed balances
- Cache invalidation on transaction creation
- Background jobs for pre-calculating aggregations
- API rate limiting to handle millions of requests
- Request queuing for batch processing
- Load balancing for horizontal scaling
- User IDs are UUIDs: Following best practices for distributed systems
- Points are decimal values: Supporting fractional points (e.g., 10.5 points)
- Time-based aggregations: All date filters use ISO 8601 format
- Partner identification: Partners are identified by simple string IDs
- Metadata flexibility: JSONB field for storing additional transaction data
- Authentication & Authorization: JWT-based user authentication
- API Documentation: Swagger/OpenAPI documentation
- Monitoring & Logging: Structured logging with correlation IDs
- Message Queue Integration: Async processing for high-volume transactions
- Data Archiving: Archive old transactions for performance
- Real-time Analytics: WebSocket endpoints for real-time updates
- Framework: NestJS with TypeScript
- Database: PostgreSQL with TypeORM
- Validation: class-validator and class-transformer
- Testing: Jest with TypeScript support
- Configuration: @nestjs/config with environment variables
src/
├── aggregations/ # Aggregation module
│ ├── aggregations.controller.ts
│ ├── aggregations.service.ts
│ ├── aggregations.service.spec.ts
│ └── aggregations.module.ts
├── transactions/ # Transaction module
│ ├── transactions.controller.ts
│ ├── transactions.service.ts
│ ├── transactions.service.spec.ts
│ └── transactions.module.ts
├── common/ # Shared components
│ ├── entities/ # Database entities
│ ├── interfaces/ # TypeScript interfaces
│ ├── dtos/ # Data Transfer Objects
│ └── mocks/ # Mock data
├── app.module.ts # Main application module
└── main.ts # Application entry point
This project is licensed under the MIT License.