Investment Module (Strategies, Participations)
Overview
The Investment Module manages the investment marketplace of the IWM Platform, allowing users to participate in various investment strategies. It handles strategy configuration, multi-step participation wizards, investment lifecycle management, portfolio tracking, and returns distribution. The module integrates with the MLM Module for referral attribution and commission calculation.
Responsibilities
- Investment strategy management
- Strategy categorization and discovery
- Multi-step participation wizard
- Investment lifecycle tracking
- Portfolio aggregation and reporting
- Returns calculation and distribution
- Early withdrawal handling
- Referral attribution for investments
Domain Entities
Strategy
Investment strategy definition.
| Field | Type | Description |
|---|---|---|
| id | UUID | Strategy identifier |
| category_id | UUID | Category reference |
| name | VARCHAR(200) | Strategy name |
| code | VARCHAR(50) | Unique strategy code |
| slug | VARCHAR(200) | URL-friendly identifier |
| short_description | VARCHAR(500) | Brief description |
| description | TEXT | Full description |
| terms | TEXT | Legal terms and conditions |
| risk_level | ENUM | LOW, MEDIUM, HIGH, VERY_HIGH |
| min_amount | DECIMAL | Minimum investment |
| max_amount | DECIMAL | Maximum investment (optional) |
| duration_months | INT | Investment term |
| expected_return_min | DECIMAL | Minimum expected return % |
| expected_return_max | DECIMAL | Maximum expected return % |
| image_url | VARCHAR(500) | Strategy image |
| documents_urls | JSONB | Related documents |
| status | ENUM | Strategy status |
| participants_count | INT | Active participants |
| total_invested | DECIMAL | Total amount invested |
| published_at | TIMESTAMP | Publication date |
StrategyCategory
Category for organizing strategies.
| Field | Type | Description |
|---|---|---|
| id | UUID | Category identifier |
| name | VARCHAR(100) | Category name |
| slug | VARCHAR(100) | URL-friendly identifier |
| description | TEXT | Category description |
| parent_id | UUID | Parent category |
| sort_order | INT | Display order |
| is_active | BOOLEAN | Active status |
ParticipationStep
Wizard step configuration for a strategy.
| Field | Type | Description |
|---|---|---|
| id | UUID | Step identifier |
| strategy_id | UUID | Strategy reference |
| step_number | INT | Step order |
| title | VARCHAR(200) | Step title |
| description | TEXT | Step instructions |
| step_type | ENUM | Step type |
| config | JSONB | Step configuration |
| is_required | BOOLEAN | Required flag |
Participation
User's investment participation.
| Field | Type | Description |
|---|---|---|
| id | UUID | Participation identifier |
| user_id | UUID | Investor reference |
| strategy_id | UUID | Strategy reference |
| current_step | INT | Current wizard step |
| step_data | JSONB | Collected wizard data |
| amount | DECIMAL | Investment amount |
| currency | VARCHAR(3) | Currency code |
| status | ENUM | Participation status |
| referring_partner_id | UUID | MLM attribution |
| started_at | TIMESTAMP | Wizard start time |
| submitted_at | TIMESTAMP | Submission time |
| approved_at | TIMESTAMP | Approval time |
| completed_at | TIMESTAMP | Completion time |
Portfolio
User's active investment portfolio entry.
| Field | Type | Description |
|---|---|---|
| id | UUID | Portfolio entry identifier |
| user_id | UUID | Investor reference |
| participation_id | UUID | Source participation |
| strategy_id | UUID | Strategy reference |
| invested_amount | DECIMAL | Original investment |
| current_value | DECIMAL | Current value |
| total_returns | DECIMAL | Accumulated returns |
| currency | VARCHAR(3) | Currency code |
| status | ENUM | Portfolio status |
| start_date | DATE | Investment start |
| maturity_date | DATE | Expected maturity |
| last_updated_at | TIMESTAMP | Last value update |
Strategy Types and Configuration
Risk Levels
| Risk Level | Expected Return | Volatility | Suitable For |
|---|---|---|---|
| LOW | 5-8% annual | Low | Conservative investors |
| MEDIUM | 8-15% annual | Moderate | Balanced portfolios |
| HIGH | 15-25% annual | High | Growth seekers |
| VERY_HIGH | 25%+ annual | Very High | Risk-tolerant investors |
Strategy Status Flow
Strategy Configuration Example
json
{
"name": "Growth Portfolio 2024",
"code": "GROWTH_2024",
"risk_level": "HIGH",
"min_amount": 50000,
"max_amount": 5000000,
"duration_months": 12,
"expected_return_min": 15.0,
"expected_return_max": 25.0,
"terms": "Investment terms and conditions...",
"documents_urls": [
{"type": "prospectus", "url": "/docs/growth-2024-prospectus.pdf"},
{"type": "risk_disclosure", "url": "/docs/risk-disclosure.pdf"}
]
}Participation Wizard
Multi-Step Process
The participation wizard guides users through the investment process:
Step Types
| Type | Description | Configuration |
|---|---|---|
| INFO | Read-only information display | content, acknowledgement |
| FORM | Data collection form | fields, validation rules |
| DOCUMENT_UPLOAD | File upload requirement | document_types, max_size |
| KYC_CHECK | KYC verification gate | required_level |
| PAYMENT | Payment processing | payment_methods |
| CONFIRMATION | Final review and submit | summary_fields |
Step Configuration Examples
INFO Step:
json
{
"step_type": "INFO",
"config": {
"content": "Strategy overview and risk disclosure...",
"acknowledgement_required": true,
"acknowledgement_text": "I have read and understood the risks"
}
}FORM Step:
json
{
"step_type": "FORM",
"config": {
"fields": [
{
"name": "investment_amount",
"type": "number",
"label": "Investment Amount",
"min": 50000,
"max": 5000000,
"required": true
},
{
"name": "investment_goal",
"type": "select",
"label": "Investment Goal",
"options": ["retirement", "education", "wealth_growth"],
"required": true
}
]
}
}KYC_CHECK Step:
json
{
"step_type": "KYC_CHECK",
"config": {
"required_level": "STANDARD",
"allow_skip": false,
"redirect_to_kyc": true
}
}Validation at Each Step
Investment Lifecycle
Participation Status Flow
Status Definitions
| Status | Description |
|---|---|
| IN_PROGRESS | User completing wizard steps |
| PENDING_APPROVAL | Submitted, awaiting approval |
| ACTIVE | Investment is active |
| COMPLETED | Investment matured successfully |
| WITHDRAWN | Early withdrawal processed |
| CANCELLED | User cancelled before activation |
| REJECTED | Admin rejected application |
Portfolio Status Flow
Portfolio Aggregation
Portfolio Calculations
Portfolio Metrics
| Metric | Calculation |
|---|---|
| Total Invested | Sum of all invested_amount |
| Current Value | Sum of all current_value |
| Total Returns | Sum of all total_returns |
| ROI | (Current Value - Total Invested) / Total Invested * 100 |
| Active Investments | Count where status = ACTIVE |
Portfolio by Strategy
sql
SELECT
s.name as strategy_name,
COUNT(*) as investments,
SUM(p.invested_amount) as total_invested,
SUM(p.current_value) as current_value,
SUM(p.total_returns) as returns
FROM portfolios p
JOIN strategies s ON p.strategy_id = s.id
WHERE p.user_id = :userId
GROUP BY s.id, s.name;Returns Distribution
Distribution Flow
Return Calculation Methods
| Method | Description | Use Case |
|---|---|---|
| Fixed | Fixed percentage per period | Conservative strategies |
| Variable | Based on market performance | Growth strategies |
| Tiered | Different rates based on amount | Large investor incentives |
| Compound | Returns reinvested | Long-term strategies |
Returns Distribution Schedule
| Frequency | Description |
|---|---|
| Monthly | Returns calculated and distributed monthly |
| Quarterly | Every 3 months |
| At Maturity | Single distribution at end of term |
| Continuous | Daily accrual, monthly distribution |
Returns Crediting
Returns can be credited to:
- User Balance - Available for withdrawal or reinvestment
- Reinvestment - Automatically added to portfolio
- MLM Balance - If user is also a partner
Early Withdrawal
Withdrawal Rules
| Withdrawal Timing | Penalty | Conditions |
|---|---|---|
| 0-3 months | 10% of returns | Full principal returned |
| 3-6 months | 5% of returns | Full principal returned |
| 6-12 months | 2% of returns | Full principal returned |
| After maturity | No penalty | Full value available |
Early Withdrawal Flow
Penalty Calculation
typescript
function calculateWithdrawalAmount(
portfolio: Portfolio,
currentDate: Date
): WithdrawalResult {
const monthsInvested = differenceInMonths(currentDate, portfolio.start_date);
let penaltyRate = 0;
if (monthsInvested < 3) penaltyRate = 0.10;
else if (monthsInvested < 6) penaltyRate = 0.05;
else if (monthsInvested < 12) penaltyRate = 0.02;
const returns = portfolio.current_value - portfolio.invested_amount;
const penalty = returns * penaltyRate;
const finalAmount = portfolio.current_value - penalty;
return {
invested_amount: portfolio.invested_amount,
returns: returns,
penalty: penalty,
final_amount: finalAmount
};
}Events Published
| Event | Trigger | Payload |
|---|---|---|
| StrategyCreated | New strategy created | strategyId, code, name |
| StrategyPublished | Strategy goes live | strategyId, publishedAt |
| StrategyStatusChanged | Status transition | strategyId, fromStatus, toStatus |
| ParticipationStarted | User begins wizard | participationId, userId, strategyId |
| ParticipationStepCompleted | Wizard step done | participationId, stepNumber, stepData |
| ParticipationSubmitted | Wizard completed | participationId, userId, amount |
| ParticipationApproved | Admin approves | participationId, approvedBy |
| ParticipationRejected | Admin rejects | participationId, reason |
| ParticipationActivated | Investment active | participationId, portfolioId |
| ParticipationCancelled | User cancels | participationId, reason |
| InvestmentMatured | Term completed | portfolioId, finalValue |
| ReturnsDistributed | Returns credited | portfolioId, amount, period |
| WithdrawalRequested | User requests withdrawal | portfolioId, amount |
| WithdrawalCompleted | Withdrawal processed | portfolioId, amount, penalty |
| PortfolioValueUpdated | Value recalculated | portfolioId, previousValue, newValue |
Events Consumed
| Event | Source | Handler |
|---|---|---|
| ReferralAttributed | MLM | Store referral on participation |
| PaymentReceived | Commerce | Activate participation |
| PaymentFailed | Commerce | Cancel participation |
| KycApproved | Core | Unblock KYC-gated participations |
Business Rules and Invariants
Strategy Rules
- Minimum amount must be positive
- Maximum amount must be greater than minimum (if set)
- Expected return max must be >= min
- Duration must be positive (if set)
- Only ACTIVE strategies accept new participations
Participation Rules
- User cannot have multiple IN_PROGRESS participations for same strategy
- Amount must be within strategy min/max bounds
- All required steps must be completed before submission
- KYC level must meet strategy requirements
- Payment must be received for activation
Portfolio Rules
- Current value cannot be negative
- Invested amount is immutable after creation
- Returns are credited to total_returns
- Status must follow defined state machine
- Maturity date is calculated from start_date + duration
Returns Rules
- Returns calculated based on strategy configuration
- Early withdrawal penalties apply as defined
- Returns credited to user balance or reinvested
- MLM commissions triggered on activation (not returns)
Integration Points
Provides to Other Modules
| Interface | Consumers | Purpose |
|---|---|---|
| IInvestmentService | MLM | Get investment details for commission |
| IPortfolioService | Core | User portfolio summary |
Consumes from Other Modules
| Interface | Provider | Purpose |
|---|---|---|
| IUserLookupService | Core | Get investor details |
| IKycStatusService | Core | Check KYC level for participation |
| IAttributionService | MLM | Get referral partner for investment |
| IPaymentService | Commerce | Process investment payments |