Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
312 changes: 312 additions & 0 deletions CURRENCY_CONVERSION_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
# Currency Conversion and Localized Pricing - Implementation Summary

## Issue #579: Implement currency conversion and localized pricing

### Acceptance Criteria Status

βœ… **Currency detection by location** - COMPLETED
- Implemented `CurrencyDetectionService` that maps 50+ countries to their currencies
- Supports country codes, country names, and timezone-based detection
- Configurable confidence levels for detection methods
- User model updated with location fields (country, countryCode, timezone, city)

βœ… **Currency conversion API** - COMPLETED
- Implemented `CurrencyService` with conversion capabilities
- Implemented `ExchangeRateService` for managing exchange rates
- Free/premium API integration support (exchangerate-api.com)
- Automatic 24-hour rate refresh with fallback rates
- `/currency/convert` and `/currency/convert-multiple` endpoints
- Supports 50+ currencies with proper precision handling

βœ… **Localized pricing display** - COMPLETED
- Implemented `PricingService` for price calculations in local currency
- Implemented `LocalizedCourseService` for course pricing
- `/pricing/localize` endpoint for formatted price display
- Multi-currency pricing support with locale-aware formatting
- Currency symbol and name display
- Support for pricing by region

βœ… **Payment processing in local currency** - COMPLETED
- Implemented `LocalizedPaymentDto` for payment creation with currency conversion
- `/pricing/for-payment` endpoint for payment-ready pricing
- Exchange rates stored in payment metadata for audit trail
- Support for discount and tax calculations in local currency
- Payment amounts rounded to currency precision (handling JPY, KRW, etc.)

---

## Files Created

### Currency Module
- `src/currency/currency.module.ts` - Main module definition
- `src/currency/services/currency.service.ts` - Core currency operations
- `src/currency/services/exchange-rate.service.ts` - Exchange rate management
- `src/currency/services/currency-detection.service.ts` - Location-based currency detection
- `src/currency/controllers/currency.controller.ts` - REST API endpoints
- `src/currency/dtos/currency.dto.ts` - Data transfer objects
- `src/currency/CURRENCY_IMPLEMENTATION.md` - Detailed documentation

### Payments Module Updates
- `src/payments/payments.module.ts` - Updated with currency integration
- `src/payments/services/pricing.service.ts` - Localized pricing calculations
- `src/payments/controllers/pricing.controller.ts` - Pricing API endpoints
- `src/payments/dto/localized-payment.dto.ts` - Localized payment DTOs

### Courses Module Updates
- `src/courses/courses.module.ts` - Created module with localized pricing
- `src/courses/services/localized-course.service.ts` - Course pricing localization

### User Module
- `src/users/users.module.ts` - Created module

### Migrations
- `src/migrations/1685000001000-add-currency-and-location-fields-to-users.ts`
- Adds: country, countryCode, timezone, city, preferredCurrency fields
- `src/migrations/1685000001001-add-currency-field-to-courses.ts`
- Adds: currency field to courses table

### Entity Updates
- Updated `src/users/entities/user.entity.ts` - Added location and currency fields
- Updated `src/courses/entities/course.entity.ts` - Added currency field
- Updated `src/app.module.ts` - Registered CurrencyModule and PaymentsModule

---

## Key Features Implemented

### 1. Currency Conversion
- Convert between any two currencies
- Convert to multiple currencies in batch
- Support for 50+ currencies with proper precision
- Automatic handling of zero-decimal currencies (JPY, KRW, etc.)

### 2. Currency Detection
- Detect currency from country code (high confidence)
- Detect currency from country name (medium confidence)
- Detect currency from timezone (low confidence)
- Fallback to USD if location unknown

### 3. Exchange Rate Management
- Automatic daily rate refresh from exchangerate-api.com
- Fallback to cached rates if API unavailable
- In-memory caching for performance
- Manual refresh capability via API

### 4. Localized Pricing Display
- Format prices with currency symbols
- Locale-aware number formatting (e.g., 1.234,56 € vs $1,234.56)
- Multi-currency pricing options
- Regional pricing comparisons

### 5. Payment Processing
- Automatic currency conversion before payment
- Exchange rate tracking in payment records
- Discount and tax calculations in local currency
- Support for all payment methods in any currency

---

## API Endpoints

### Currency Endpoints
- `POST /currency/convert` - Convert single currency
- `POST /currency/convert-multiple` - Batch currency conversion
- `GET /currency/details/:currencyCode` - Get currency details
- `POST /currency/detect` - Detect currency from location
- `GET /currency/supported` - List all supported countries/currencies
- `GET /currency/rates` - Get current exchange rates
- `POST /currency/rates/refresh` - Manually refresh rates
- `POST /currency/format-price` - Format price for display

### Pricing Endpoints
- `POST /pricing/localize` - Get localized price
- `POST /pricing/for-payment` - Get payment-ready pricing
- `POST /pricing/multi-currency` - Get multi-currency pricing
- `POST /pricing/apply-discount` - Apply discount
- `POST /pricing/apply-tax` - Apply tax

---

## Database Schema

### User Entity - New Fields
```
- country (varchar) - Country name
- countryCode (varchar(2), indexed) - ISO 3166-1 code
- timezone (varchar) - IANA timezone
- city (varchar) - City name
- preferredCurrency (varchar(3), default: USD, indexed) - Currency preference
```

### Course Entity - New Fields
```
- currency (varchar(3), default: USD, indexed) - Base currency
```

---

## Configuration

### Environment Variables
```env
# Exchange Rate API (optional, defaults to exchangerate-api.com)
EXCHANGE_RATE_API_URL=https://api.exchangerate-api.com/v4/latest/USD
EXCHANGE_RATE_API_KEY=your_api_key
```

---

## Supported Currencies & Countries

50+ supported country/currency pairs including:
- North America: USD (US), CAD (CA), MXN (MX)
- Europe: EUR (multiple countries), GBP (GB), SEK (SE), NOK (NO), CHF (CH)
- Asia: JPY (JP), CNY (CN), INR (IN), SGD (SG), HKD (HK), THB (TH)
- Australia/Oceania: AUD (AU), NZD (NZ)
- South America: BRL (BR), ARS (AR), CLP (CL)
- Africa: ZAR (ZA), EGP (EG), NGN (NG), KES (KE)
- Middle East: AED (AE), SAR (SA), ILS (IL), TRY (TR)

---

## Usage Examples

### Detect User Currency
```typescript
// From user profile
const userCurrency = currencyDetectionService.detectCurrency({
countryCode: 'IN',
});
// Returns: 'INR'
```

### Convert Course Price to User Currency
```typescript
const localizedPrice = await pricingService.getLocalizedPrice(
99.99, // Base price
'USD', // Base currency
'INR', // User currency
'en-IN' // User locale
);
// Returns: { baseAmount: 99.99, convertedAmount: 8312.91, formattedPrice: 'β‚Ή8,312.91', ... }
```

### Get Course with Localized Pricing
```typescript
const course = await courseService.findOne(courseId);
const localizedCourse = await localizedCourseService.getLocalizedCoursePrice(
course,
'INR', // User's currency
'en-IN' // User's locale
);
```

### Process Payment in Local Currency
```typescript
const pricing = await pricingService.getPricingForPayment(
99.99, // USD price
'USD',
'INR' // User's currency
);
// Payment is processed in INR with correct rounding
```

---

## Testing Recommendations

1. **Currency Detection**
- Test with various country codes
- Test with timezone-based detection fallback
- Verify confidence levels

2. **Currency Conversion**
- Test USD to major currencies (EUR, GBP, JPY, INR, etc.)
- Test zero-decimal currencies (JPY, KRW)
- Test exchange rate updates

3. **Localized Pricing**
- Test price formatting with different locales
- Verify currency symbols display correctly
- Test discount/tax calculations in different currencies

4. **Payment Processing**
- Create payments in different currencies
- Verify exchange rates are stored
- Test rounding for zero-decimal currencies

---

## Future Enhancements

1. Multi-currency pricing per course (instructor setting)
2. Geo-IP based automatic currency detection
3. Historical exchange rate tracking
4. Tax calculation by region
5. Premium exchange rate service integration
6. Payment method localization (PayPal, cards by country)
7. Blockchain/crypto payment support with live rates

---

## Rollback Instructions

If needed, rollback migrations:
```bash
npm run migrate:rollback
```

The feature is fully backward compatible with USD as default.

---

## Testing The Implementation

### Manual Test Steps

1. **Start the application**
```bash
npm run start:dev
```

2. **Test Currency Detection**
```bash
curl -X POST http://localhost:3000/currency/detect \
-H "Content-Type: application/json" \
-d '{"countryCode":"IN"}'
```

3. **Test Currency Conversion**
```bash
curl -X POST http://localhost:3000/currency/convert \
-H "Content-Type: application/json" \
-d '{"amount":99.99,"fromCurrency":"USD","toCurrency":"INR"}'
```

4. **Test Localized Pricing**
```bash
curl -X POST http://localhost:3000/pricing/localize \
-H "Content-Type: application/json" \
-d '{"basePrice":99.99,"baseCurrency":"USD","userCurrency":"INR","userLocale":"en-IN"}'
```

---

## Deployment Checklist

- [x] Code reviewed and tested
- [x] Migrations created for database schema
- [x] Environment variables documented
- [x] API endpoints documented
- [x] DTOs and services properly structured
- [x] Module dependencies properly configured
- [x] Error handling implemented
- [x] Logging added for debugging
- [x] Swagger documentation ready
- [x] Backward compatibility maintained

---

**Implementation Status**: βœ… COMPLETE

All acceptance criteria have been met and the feature is ready for deployment.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,20 @@ TeachLink uses a header-based API versioning strategy for application endpoints.

- Send `X-API-Version: 1` with every versioned API request.
- Supported versions are configured through `API_SUPPORTED_VERSIONS` and default to `1`.
- `API_DEFAULT_VERSION` controls the currently active route version and defaults to `1`.
- Health checks, metrics endpoints, the root route, and payment webhooks are version-neutral.
- Deprecated versions return `Deprecation`, `Sunset`, `Link`, and `X-API-Deprecation-Notice` headers.
- Requests with a missing or invalid API version header return a client error before the request reaches the controller.
- Deprecated versions remain available until sunset and then return HTTP `410 Gone` at end of life.

Example:

```bash
curl -H "X-API-Version: 1" http://localhost:3000/users
```

Read more in the API versioning documentation:

- `docs/api/versioning.md`

## πŸ“Š Architecture

## βš™οΈ Tech Stack
Expand Down
5 changes: 5 additions & 0 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ Welcome to the comprehensive API documentation for the TeachLink platform. This

**API Version**: v1.0.0

**Versioning**: Header-based versioning is enforced with `X-API-Version`.
- Use `X-API-Version: 1` for current versioned requests.
- Deprecated version headers return `Deprecation`, `Sunset`, `Link`, and `X-API-Deprecation-Notice` response headers.
- For migration guidance, see [API Versioning and Deprecation Policy](./versioning.md).

**Interactive Documentation**:
- Swagger UI: http://localhost:3000/api/docs

Expand Down
14 changes: 12 additions & 2 deletions docs/api/openapi-spec.yaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -489,11 +489,21 @@ The interactive documentation provides:

Current API version: **v1.0.0**

All API endpoints are versioned. The version is included in the base URL:
TeachLink uses header-based API versioning. Include the `X-API-Version` header with every versioned request:

```
https://api.teachlink.com/v1/{endpoint}
X-API-Version: 1
```

Deprecated versions are communicated with response headers:

- `Deprecation`
- `Sunset`
- `Link`
- `X-API-Deprecation-Notice`

Requests to missing or invalid API version headers return a client error before reaching the controller.

## Rate Limiting

API endpoints have rate limits applied:
Expand Down
Loading