trading-platform-backend/src/modules/investment/controllers/investment.controller.ts

531 lines
12 KiB
TypeScript

/**
* Investment Controller
* Handles investment-related endpoints
*/
import { Request, Response, NextFunction } from 'express';
import { productService, RiskProfile } from '../services/product.service';
import { accountService, CreateAccountInput } from '../services/account.service';
import {
transactionService,
TransactionType,
TransactionStatus,
WithdrawalStatus,
} from '../services/transaction.service';
// ============================================================================
// Types
// ============================================================================
// Use Request directly - user is already declared globally in auth.middleware.ts
type AuthRequest = Request;
// ============================================================================
// Product Controllers
// ============================================================================
/**
* Get all investment products
*/
export async function getProducts(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { riskProfile } = req.query;
let products;
if (riskProfile) {
products = await productService.getProductsByRiskProfile(riskProfile as RiskProfile);
} else {
products = await productService.getProducts();
}
res.json({
success: true,
data: products,
});
} catch (error) {
next(error);
}
}
/**
* Get product by ID
*/
export async function getProductById(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { productId } = req.params;
const product = await productService.getProductById(productId);
if (!product) {
res.status(404).json({
success: false,
error: { message: 'Product not found', code: 'NOT_FOUND' },
});
return;
}
// Get additional stats
const stats = await productService.getProductStats(productId);
res.json({
success: true,
data: { ...product, stats },
});
} catch (error) {
next(error);
}
}
/**
* Get product performance
*/
export async function getProductPerformance(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const { productId } = req.params;
const { period = 'month' } = req.query;
const performance = await productService.getProductPerformance(
productId,
period as 'week' | 'month' | '3months' | 'year'
);
res.json({
success: true,
data: performance,
});
} catch (error) {
next(error);
}
}
// ============================================================================
// Account Controllers
// ============================================================================
/**
* Get user accounts
*/
export async function getUserAccounts(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const accounts = await accountService.getUserAccounts(userId);
res.json({
success: true,
data: accounts,
});
} catch (error) {
next(error);
}
}
/**
* Get account summary
*/
export async function getAccountSummary(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const summary = await accountService.getAccountSummary(userId);
res.json({
success: true,
data: summary,
});
} catch (error) {
next(error);
}
}
/**
* Get account by ID
*/
export async function getAccountById(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
// Get performance history
const performance = await accountService.getAccountPerformance(accountId, 30);
res.json({
success: true,
data: { ...account, performance },
});
} catch (error) {
next(error);
}
}
/**
* Create investment account
*/
export async function createAccount(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { productId, initialDeposit } = req.body;
if (!productId || !initialDeposit) {
res.status(400).json({
success: false,
error: { message: 'Product ID and initial deposit are required', code: 'VALIDATION_ERROR' },
});
return;
}
const input: CreateAccountInput = {
userId,
productId,
initialDeposit: Number(initialDeposit),
};
const account = await accountService.createAccount(input);
res.status(201).json({
success: true,
data: account,
});
} catch (error) {
next(error);
}
}
/**
* Close account
*/
export async function closeAccount(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
const closedAccount = await accountService.closeAccount(accountId);
res.json({
success: true,
data: closedAccount,
});
} catch (error) {
next(error);
}
}
// ============================================================================
// Transaction Controllers
// ============================================================================
/**
* Get account transactions
*/
export async function getTransactions(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const { type, status, limit = 50, offset = 0 } = req.query;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
const { transactions, total } = await transactionService.getAccountTransactions(accountId, {
type: type as TransactionType | undefined,
status: status as TransactionStatus | undefined,
limit: Number(limit),
offset: Number(offset),
});
res.json({
success: true,
data: transactions,
pagination: {
total,
limit: Number(limit),
offset: Number(offset),
},
});
} catch (error) {
next(error);
}
}
/**
* Create deposit
*/
export async function createDeposit(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const { amount } = req.body;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
if (!amount || amount <= 0) {
res.status(400).json({
success: false,
error: { message: 'Valid amount is required', code: 'VALIDATION_ERROR' },
});
return;
}
const transaction = await transactionService.createDeposit({
accountId,
amount: Number(amount),
});
res.status(201).json({
success: true,
data: transaction,
});
} catch (error) {
next(error);
}
}
/**
* Create withdrawal request
*/
export async function createWithdrawal(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const { amount, bankInfo, cryptoInfo } = req.body;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
if (!amount || amount <= 0) {
res.status(400).json({
success: false,
error: { message: 'Valid amount is required', code: 'VALIDATION_ERROR' },
});
return;
}
const withdrawal = await transactionService.createWithdrawal(userId, {
accountId,
amount: Number(amount),
bankInfo,
cryptoInfo,
});
res.status(201).json({
success: true,
data: withdrawal,
message: 'Withdrawal request submitted. Processing time: 72 hours.',
});
} catch (error) {
next(error);
}
}
/**
* Get user withdrawals
*/
export async function getWithdrawals(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { status } = req.query;
const withdrawals = await transactionService.getUserWithdrawals(
userId,
status as WithdrawalStatus | undefined
);
res.json({
success: true,
data: withdrawals,
});
} catch (error) {
next(error);
}
}
/**
* Get account distributions
*/
export async function getDistributions(req: AuthRequest, res: Response, next: NextFunction): Promise<void> {
try {
const userId = req.user?.id;
if (!userId) {
res.status(401).json({
success: false,
error: { message: 'Unauthorized', code: 'UNAUTHORIZED' },
});
return;
}
const { accountId } = req.params;
const account = await accountService.getAccountById(accountId);
if (!account) {
res.status(404).json({
success: false,
error: { message: 'Account not found', code: 'NOT_FOUND' },
});
return;
}
if (account.userId !== userId) {
res.status(403).json({
success: false,
error: { message: 'Forbidden', code: 'FORBIDDEN' },
});
return;
}
const distributions = await transactionService.getAccountDistributions(accountId);
res.json({
success: true,
data: distributions,
});
} catch (error) {
next(error);
}
}