- number-поля теперь рендерятся как text + inputMode=numeric, чтобы браузер не округлял значения через input type=number - пробелы при вставке в number-поля удаляются - бэкенд нормализует значения number-полей в строку перед сохранением - добавлен хелпер normalizeFieldValueForStorage Closes: искажение расчётного счёта и других длинных числовых полей
131 lines
4.8 KiB
TypeScript
131 lines
4.8 KiB
TypeScript
import { storage } from "../storage";
|
|
import { authenticateToken, requirePermission, type AuthenticatedRequest } from "../middleware/auth.middleware";
|
|
import { tenantIsolation } from "../middleware/tenant.middleware";
|
|
import { validateRequest } from "../middleware/validation.middleware";
|
|
import { createBotSubscriptionSchema } from "@shared/schema";
|
|
|
|
export function registerBotSubscriptionRoutes(app: import("express").Express): void {
|
|
// Delete bot (admin only)
|
|
app.delete('/api/bots/:id',
|
|
authenticateToken,
|
|
requirePermission('bots.manage'),
|
|
tenantIsolation,
|
|
async (req: AuthenticatedRequest, res) => {
|
|
try {
|
|
const botId = parseInt(req.params.id);
|
|
if (isNaN(botId)) {
|
|
return res.status(400).json({ success: false, error: 'Некорректный ID бота' });
|
|
}
|
|
|
|
const bot = await storage.getBot(botId, req.organizationId!);
|
|
if (!bot) {
|
|
return res.status(404).json({ success: false, error: 'Бот не найден' });
|
|
}
|
|
|
|
await storage.deleteBot(botId, req.organizationId!);
|
|
|
|
res.json({ success: true, message: 'Бот удален' });
|
|
} catch (error) {
|
|
console.error('Delete bot error:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка при удалении бота' });
|
|
}
|
|
}
|
|
);
|
|
|
|
// Get bot subscriptions
|
|
app.get('/api/bots/:id/subscriptions',
|
|
authenticateToken,
|
|
requirePermission('bots.manage'),
|
|
tenantIsolation,
|
|
async (req: AuthenticatedRequest, res) => {
|
|
try {
|
|
const botId = parseInt(req.params.id);
|
|
if (isNaN(botId)) {
|
|
return res.status(400).json({ success: false, error: 'Некорректный ID бота' });
|
|
}
|
|
|
|
const bot = await storage.getBot(botId, req.organizationId!);
|
|
if (!bot) {
|
|
return res.status(404).json({ success: false, error: 'Бот не найден' });
|
|
}
|
|
|
|
const subscriptions = await storage.getBotSubscriptions(botId, req.organizationId!);
|
|
|
|
res.json({ success: true, subscriptions });
|
|
} catch (error) {
|
|
console.error('Get bot subscriptions error:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка при получении подписок бота' });
|
|
}
|
|
}
|
|
);
|
|
|
|
// Create bot subscription
|
|
app.post('/api/bots/:id/subscriptions',
|
|
authenticateToken,
|
|
requirePermission('bots.manage'),
|
|
tenantIsolation,
|
|
validateRequest(createBotSubscriptionSchema),
|
|
async (req: AuthenticatedRequest, res) => {
|
|
try {
|
|
const botId = parseInt(req.params.id);
|
|
if (isNaN(botId)) {
|
|
return res.status(400).json({ success: false, error: 'Некорректный ID бота' });
|
|
}
|
|
|
|
const bot = await storage.getBot(botId, req.organizationId!);
|
|
if (!bot) {
|
|
return res.status(404).json({ success: false, error: 'Бот не найден' });
|
|
}
|
|
|
|
const { subscriptionType, formId, statusId, transitionId, events, filters } = req.body;
|
|
|
|
const subscription = await storage.createBotSubscription({
|
|
botId,
|
|
organizationId: req.organizationId!,
|
|
subscriptionType,
|
|
formId: formId || null,
|
|
statusId: statusId || null,
|
|
transitionId: transitionId || null,
|
|
events,
|
|
filters: filters || null,
|
|
isActive: true
|
|
});
|
|
|
|
res.status(201).json({ success: true, message: 'Подписка создана', subscription });
|
|
} catch (error) {
|
|
console.error('Create bot subscription error:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка при создании подписки' });
|
|
}
|
|
}
|
|
);
|
|
|
|
// Delete bot subscription
|
|
app.delete('/api/bots/:botId/subscriptions/:subscriptionId',
|
|
authenticateToken,
|
|
requirePermission('bots.manage'),
|
|
tenantIsolation,
|
|
async (req: AuthenticatedRequest, res) => {
|
|
try {
|
|
const botId = parseInt(req.params.botId);
|
|
const subscriptionId = parseInt(req.params.subscriptionId);
|
|
|
|
if (isNaN(botId) || isNaN(subscriptionId)) {
|
|
return res.status(400).json({ success: false, error: 'Некорректный ID' });
|
|
}
|
|
|
|
const bot = await storage.getBot(botId, req.organizationId!);
|
|
if (!bot) {
|
|
return res.status(404).json({ success: false, error: 'Бот не найден' });
|
|
}
|
|
|
|
await storage.deleteBotSubscription(subscriptionId, req.organizationId!);
|
|
|
|
res.json({ success: true, message: 'Подписка удалена' });
|
|
} catch (error) {
|
|
console.error('Delete bot subscription error:', error);
|
|
res.status(500).json({ success: false, error: 'Ошибка при удалении подписки' });
|
|
}
|
|
}
|
|
);
|
|
}
|