Initial commit: Telegram Management System
Some checks failed
Deploy / deploy (push) Has been cancelled
Some checks failed
Deploy / deploy (push) Has been cancelled
Full-stack web application for Telegram management - Frontend: Vue 3 + Vben Admin - Backend: NestJS - Features: User management, group broadcast, statistics 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
import express from 'express';
|
||||
import { transactionService } from '../services/transactionService.js';
|
||||
import { authenticate, requireTenant, requireAdmin } from '../middleware/auth.js';
|
||||
import { validateRequest } from '../middleware/validation.js';
|
||||
import { body, param, query } from 'express-validator';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// Get transactions
|
||||
router.get('/',
|
||||
authenticate,
|
||||
requireTenant,
|
||||
validateRequest([
|
||||
query('type').optional().isIn(['payment', 'refund', 'adjustment', 'fee']),
|
||||
query('status').optional().isIn(['pending', 'processing', 'succeeded', 'failed', 'canceled']),
|
||||
query('startDate').optional().isISO8601(),
|
||||
query('endDate').optional().isISO8601(),
|
||||
query('limit').optional().isInt({ min: 1, max: 100 }),
|
||||
query('offset').optional().isInt({ min: 0 })
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const transactions = await transactionService.getTransactions(
|
||||
req.tenantId,
|
||||
req.query
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
transactions
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Get transactions error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to get transactions'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Get transaction by ID
|
||||
router.get('/:id',
|
||||
authenticate,
|
||||
requireTenant,
|
||||
validateRequest([
|
||||
param('id').isMongoId()
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const transaction = await transactionService.getTransaction(
|
||||
req.tenantId,
|
||||
req.params.id
|
||||
);
|
||||
|
||||
if (!transaction) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
error: 'Transaction not found'
|
||||
});
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
transaction
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Get transaction error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to get transaction'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Create refund
|
||||
router.post('/:id/refund',
|
||||
authenticate,
|
||||
requireTenant,
|
||||
validateRequest([
|
||||
param('id').isMongoId(),
|
||||
body('amount').optional().isFloat({ min: 0 }),
|
||||
body('reason').notEmpty(),
|
||||
body('metadata').optional().isObject()
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const refund = await transactionService.createRefund(
|
||||
req.tenantId,
|
||||
req.params.id,
|
||||
{
|
||||
...req.body,
|
||||
initiatedBy: req.user.id
|
||||
}
|
||||
);
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
refund,
|
||||
message: 'Refund initiated successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Create refund error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to create refund'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Get transaction summary
|
||||
router.get('/summary/:period',
|
||||
authenticate,
|
||||
requireTenant,
|
||||
validateRequest([
|
||||
param('period').isIn(['daily', 'weekly', 'monthly', 'yearly']),
|
||||
query('startDate').optional().isISO8601(),
|
||||
query('endDate').optional().isISO8601()
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const summary = await transactionService.getTransactionSummary(
|
||||
req.tenantId,
|
||||
req.params.period,
|
||||
{
|
||||
startDate: req.query.startDate,
|
||||
endDate: req.query.endDate
|
||||
}
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
summary
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Get transaction summary error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to get transaction summary'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Export transactions
|
||||
router.get('/export/:format',
|
||||
authenticate,
|
||||
requireTenant,
|
||||
validateRequest([
|
||||
param('format').isIn(['csv', 'pdf', 'excel']),
|
||||
query('startDate').optional().isISO8601(),
|
||||
query('endDate').optional().isISO8601()
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const { filename, data } = await transactionService.exportTransactions(
|
||||
req.tenantId,
|
||||
req.params.format,
|
||||
{
|
||||
startDate: req.query.startDate,
|
||||
endDate: req.query.endDate
|
||||
}
|
||||
);
|
||||
|
||||
// Set appropriate headers based on format
|
||||
const contentType = {
|
||||
csv: 'text/csv',
|
||||
pdf: 'application/pdf',
|
||||
excel: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
};
|
||||
|
||||
res.setHeader('Content-Type', contentType[req.params.format]);
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
|
||||
res.send(data);
|
||||
} catch (error) {
|
||||
logger.error('Export transactions error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to export transactions'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Admin: Create manual adjustment
|
||||
router.post('/adjustment',
|
||||
authenticate,
|
||||
requireAdmin,
|
||||
validateRequest([
|
||||
body('tenantId').isMongoId(),
|
||||
body('type').isIn(['credit', 'debit']),
|
||||
body('amount').isFloat({ min: 0 }),
|
||||
body('currency').optional().isString(),
|
||||
body('reason').notEmpty(),
|
||||
body('metadata').optional().isObject()
|
||||
]),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const adjustment = await transactionService.createAdjustment({
|
||||
...req.body,
|
||||
createdBy: req.user.id
|
||||
});
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
adjustment,
|
||||
message: 'Adjustment created successfully'
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Create adjustment error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to create adjustment'
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user