Skip to main content

Per-Cycle Payout Strategy Override

Overview

The per-cycle payout strategy override feature allows admins to set different payout strategies for individual users in specific cycles, overriding their opportunity-level default.

Use Cases

  1. Flexible Profit Management: Users can compound profits in one cycle and withdraw in another
  2. Conditional Strategies: Apply different strategies based on cycle performance
  3. Testing: Test different strategies without changing account defaults
  4. Special Arrangements: Custom profit handling for specific investors in specific cycles

Technical Implementation

Database Schema

Model: CycleInvestment

  • payoutStrategyId (optional): Foreign key to PayoutStrategy
  • When null: Uses opportunity default strategy
  • When set: Overrides opportunity default for this cycle only

API Endpoint

PATCH /api/admin/users/{id}

Request body:

{
"action": "update_cycle_strategy",
"cycleInvestmentId": 123,
"payoutStrategyId": 456
}

Set payoutStrategyId to null to clear override and revert to opportunity default.

Validation Rules

  1. Cycle Status: Only works for unsettled cycles (draft, open, active, closed)
  2. Settled Cycles: Cannot modify strategy after cycle is settled (prevents post-distribution changes)
  3. Ownership: Cycle investment must belong to the specified user
  4. Strategy Ownership: Strategy must be either:
    • System-wide (userId = null), OR
    • Belong to the user

Frontend UI

Location: /admin/users/{id} → Investments tab

Features:

  • Dropdown selector showing current strategy
  • "Use Opportunity Default" option (clears override)
  • Only visible for unsettled cycles
  • Shows active override with green checkmark
  • Immediate save on selection change
  • Loading indicator during update

How It Works

Profit Distribution Flow

  1. During Distribution (distribute_cycle_profits()):

    • System checks CycleInvestment.payoutStrategyId
    • If set: Uses cycle-specific strategy
    • If null: Falls back to opportunity default strategy
  2. Strategy Evaluation:

    • Compound: Profits → capitalAvailable (auto-reinvest)
    • Payout: Profits → profitAvailable (manual withdrawal)
    • Conditional: Evaluated based on profit percentage thresholds

Example Scenario

User: Maria (investor in Reprise Cycle #2)

Opportunity Default: Compound (auto-reinvest all profits)

Cycle #2 Override: Payout (withdraw profits)

Result:

  • Cycle #2 profits go to profitAvailable (can withdraw)
  • Future cycles without override will use Compound strategy
  • Cycle #1 (already settled) cannot be changed

Setting a Per-Cycle Override

Via Admin UI

  1. Navigate to /admin/users/{userId}
  2. Click "Investments" tab
  3. Find the cycle investment
  4. Use "Cycle-Specific Strategy Override" dropdown
  5. Select desired strategy or "Use Opportunity Default"
  6. Changes save immediately

Via API

curl -X PATCH https://app.opportunitydao.com/api/admin/users/9 \
-H "Content-Type: application/json" \
-d '{
"action": "update_cycle_strategy",
"cycleInvestmentId": 42,
"payoutStrategyId": 7
}'

Best Practices

  1. Set Before Settlement: Always configure overrides before closing/settling cycles
  2. Communication: Inform users when setting non-standard strategies
  3. Documentation: Note in admin logs why specific overrides were applied
  4. Testing: Test with small amounts first to verify behavior
  5. Review: Check overrides before each distribution

Limitations

  1. Cannot Modify Settled Cycles: Once distributed, strategy is locked
  2. Admin Only: Users cannot set their own per-cycle overrides
  3. No Bulk Operations: Each cycle must be set individually
  4. No History: Previous overrides aren't tracked after cycle settlement

Troubleshooting

Override Not Applied

Symptom: Profits distributed using opportunity default instead of override

Causes:

  1. Override not saved before distribution
  2. Override cleared accidentally
  3. Database transaction rollback

Solution: Re-distribute cycle if possible, or manually adjust balances

Cannot Select Strategy

Symptom: Dropdown disabled or strategy not available

Causes:

  1. Cycle already settled
  2. Strategy doesn't belong to user
  3. Strategy is inactive

Solution: Verify cycle status and strategy ownership

Version History

  • v0.7.0 (2025-11-05): Initial implementation
    • Added payoutStrategyId to CycleInvestment
    • Created API endpoint
    • Built admin UI with dropdown selector
    • Added validation for settled cycles