erp-mecanicas-diesel-backen.../src/modules/payment-terminals/controllers/transactions.controller.ts
Adrian Flores Cortes 5c7134cc03 [PROP-CORE-004] feat: Add Phase 6 modules from erp-core
Propagated modules:
- payment-terminals: MercadoPago + Clip TPV
- ai: Role-based AI access (ADMIN, JEFE_TALLER, MECANICO, CLIENTE)
- mcp: 18 ERP tools for AI assistants

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 02:45:37 -06:00

164 lines
4.8 KiB
TypeScript

/**
* Transactions Controller
*
* REST API endpoints for payment transactions
*/
import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { TransactionsService } from '../services';
import { ProcessPaymentDto, ProcessRefundDto, SendReceiptDto, TransactionFilterDto } from '../dto';
// Extend Request to include tenant info
interface AuthenticatedRequest extends Request {
tenantId?: string;
userId?: string;
}
export class TransactionsController {
public router: Router;
private service: TransactionsService;
constructor(dataSource: DataSource) {
this.router = Router();
this.service = new TransactionsService(dataSource);
this.initializeRoutes();
}
private initializeRoutes(): void {
// Stats
this.router.get('/stats', this.getStats.bind(this));
// Payment processing
this.router.post('/charge', this.processPayment.bind(this));
this.router.post('/refund', this.processRefund.bind(this));
// Transaction queries
this.router.get('/', this.getAll.bind(this));
this.router.get('/:id', this.getById.bind(this));
// Actions
this.router.post('/:id/receipt', this.sendReceipt.bind(this));
}
/**
* GET /payment-transactions/stats
* Get transaction statistics
*/
private async getStats(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const filter: TransactionFilterDto = {
branchId: req.query.branchId as string,
startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined,
endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined,
};
const stats = await this.service.getStats(req.tenantId!, filter);
res.json({ data: stats });
} catch (error) {
next(error);
}
}
/**
* POST /payment-transactions/charge
* Process a payment
*/
private async processPayment(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const dto: ProcessPaymentDto = req.body;
const result = await this.service.processPayment(req.tenantId!, req.userId!, dto);
if (result.success) {
res.status(201).json({ data: result });
} else {
res.status(400).json({ data: result });
}
} catch (error) {
next(error);
}
}
/**
* POST /payment-transactions/refund
* Process a refund
*/
private async processRefund(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const dto: ProcessRefundDto = req.body;
const result = await this.service.processRefund(req.tenantId!, req.userId!, dto);
if (result.success) {
res.json({ data: result });
} else {
res.status(400).json({ data: result });
}
} catch (error) {
next(error);
}
}
/**
* GET /payment-transactions
* Get transactions with filters
*/
private async getAll(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const filter: TransactionFilterDto = {
branchId: req.query.branchId as string,
userId: req.query.userId as string,
status: req.query.status as any,
sourceType: req.query.sourceType as any,
terminalProvider: req.query.terminalProvider as string,
startDate: req.query.startDate ? new Date(req.query.startDate as string) : undefined,
endDate: req.query.endDate ? new Date(req.query.endDate as string) : undefined,
limit: req.query.limit ? parseInt(req.query.limit as string) : undefined,
offset: req.query.offset ? parseInt(req.query.offset as string) : undefined,
};
const result = await this.service.findAll(req.tenantId!, filter);
res.json(result);
} catch (error) {
next(error);
}
}
/**
* GET /payment-transactions/:id
* Get transaction by ID
*/
private async getById(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const transaction = await this.service.findById(req.params.id, req.tenantId!);
if (!transaction) {
res.status(404).json({ error: 'Transaction not found' });
return;
}
res.json({ data: transaction });
} catch (error) {
next(error);
}
}
/**
* POST /payment-transactions/:id/receipt
* Send receipt for transaction
*/
private async sendReceipt(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
try {
const dto: SendReceiptDto = req.body;
const result = await this.service.sendReceipt(req.params.id, req.tenantId!, dto);
if (result.success) {
res.json({ success: true });
} else {
res.status(400).json({ success: false, error: result.error });
}
} catch (error) {
next(error);
}
}
}