141 lines
4.8 KiB
JavaScript
141 lines
4.8 KiB
JavaScript
// routes/api.js
|
||
// API маршруты для калькуляторов
|
||
|
||
const express = require('express');
|
||
const multer = require('multer');
|
||
const { getCalculator, hasCalculator } = require('../calculators');
|
||
const { sendTelegramMessage } = require('../lib/telegram');
|
||
const { validateRequiredFields, validateNumericFields } = require('../lib/validator');
|
||
|
||
const router = express.Router();
|
||
|
||
// Настраиваем multer (храним файлы в памяти)
|
||
const storage = multer.memoryStorage();
|
||
const upload = multer({ storage });
|
||
|
||
/**
|
||
* Обработчик POST /api/submit/:calculatorType
|
||
* Принимает данные калькулятора и отправляет результат в Telegram
|
||
*/
|
||
router.post(
|
||
'/submit/:calculatorType',
|
||
upload.single('photo'),
|
||
async (req, res) => {
|
||
try {
|
||
const { calculatorType } = req.params;
|
||
const { chat_id, ...formData } = req.body;
|
||
const photoFile = req.file;
|
||
|
||
// Проверяем, существует ли калькулятор
|
||
if (!hasCalculator(calculatorType)) {
|
||
return res.status(404).json({
|
||
error: `Калькулятор "${calculatorType}" не найден`,
|
||
});
|
||
}
|
||
|
||
// Получаем модуль калькулятора
|
||
const calculator = getCalculator(calculatorType);
|
||
|
||
// Валидация обязательных полей
|
||
const requiredValidation = validateRequiredFields(
|
||
{ chat_id, ...formData },
|
||
['chat_id', ...calculator.getRequiredFields()]
|
||
);
|
||
if (!requiredValidation.valid) {
|
||
return res.status(400).json({ error: requiredValidation.error });
|
||
}
|
||
|
||
// Валидация числовых полей
|
||
const numericValidation = validateNumericFields(
|
||
formData,
|
||
calculator.getNumericFields()
|
||
);
|
||
if (!numericValidation.valid) {
|
||
return res.status(400).json({ error: numericValidation.error });
|
||
}
|
||
|
||
// Подготавливаем данные для расчёта
|
||
const calculationData = prepareCalculationData(formData, calculator.fieldSchema);
|
||
|
||
// Выполняем расчёт
|
||
const calculationResult = calculator.calculate(calculationData);
|
||
|
||
// Вычисляем финальную цену и цену за 100г (если применимо)
|
||
const markup = parseFloat(formData.markup || 0);
|
||
const totalCost = calculationResult.total;
|
||
const finalPrice = totalCost * (1 + markup / 100);
|
||
const weight = parseFloat(formData.weight || 0);
|
||
const pricePer100g = weight > 0 ? (finalPrice / weight) * 100 : 0;
|
||
|
||
// Формируем сообщение для Telegram
|
||
const messageData = {
|
||
...formData,
|
||
totalCost,
|
||
finalPrice,
|
||
pricePer100g,
|
||
};
|
||
const telegramMessage = calculator.formatMessage(messageData, calculationResult);
|
||
|
||
// Отправляем в Telegram
|
||
try {
|
||
await sendTelegramMessage(
|
||
req.app.locals.bot,
|
||
chat_id,
|
||
telegramMessage,
|
||
photoFile ? photoFile.buffer : null
|
||
);
|
||
res.sendStatus(200);
|
||
} catch (telegramError) {
|
||
console.error('Ошибка при отправке в Telegram:', telegramError);
|
||
res.status(500).json({
|
||
error: 'Ошибка при отправке сообщения в Telegram',
|
||
details: telegramError.message,
|
||
});
|
||
}
|
||
} catch (err) {
|
||
console.error('Ошибка в /api/submit:', err);
|
||
res.status(500).json({
|
||
error: 'Внутренняя ошибка сервера',
|
||
details: err.message,
|
||
});
|
||
}
|
||
}
|
||
);
|
||
|
||
/**
|
||
* Подготавливает данные для расчёта из формы
|
||
* @param {Object} formData - Данные из формы
|
||
* @param {Array} fieldSchema - Схема полей калькулятора
|
||
* @returns {Object} Подготовленные данные для расчёта
|
||
*/
|
||
function prepareCalculationData(formData, fieldSchema) {
|
||
const data = {};
|
||
|
||
for (const field of fieldSchema) {
|
||
if (formData[field.name] !== undefined) {
|
||
const value = formData[field.name];
|
||
if (field.type === 'number') {
|
||
data[field.name] = parseFloat(value) || 0;
|
||
} else {
|
||
data[field.name] = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Специфичная обработка для мыла (упаковка)
|
||
if (formData.box !== undefined || formData.filler !== undefined ||
|
||
formData.ribbon !== undefined || formData.labelValue !== undefined) {
|
||
data.packaging = {
|
||
box: parseFloat(formData.box || 0),
|
||
filler: parseFloat(formData.filler || 0),
|
||
ribbon: parseFloat(formData.ribbon || 0),
|
||
label: parseFloat(formData.labelValue || 0),
|
||
};
|
||
}
|
||
|
||
return data;
|
||
}
|
||
|
||
module.exports = router;
|
||
|