115 lines
3.9 KiB
JavaScript
115 lines
3.9 KiB
JavaScript
// calculators/candle.js
|
||
// Калькулятор свечей (пример нового калькулятора)
|
||
|
||
/**
|
||
* Схема полей калькулятора
|
||
*/
|
||
const fieldSchema = [
|
||
{ id: 'candleName', name: 'candleName', label: 'Название свечи', type: 'text', required: true },
|
||
{ id: 'weight', name: 'weight', label: 'Вес свечи, г', type: 'number', required: true },
|
||
{ id: 'waxPrice', name: 'waxPrice', label: 'Цена воска за 1 кг, руб', type: 'number', required: false },
|
||
{ id: 'wickPrice', name: 'wickPrice', label: 'Цена фитиля, руб', type: 'number', required: false },
|
||
{ id: 'aromaPrice', name: 'aromaPrice', label: 'Цена отдушки, руб', type: 'number', required: false },
|
||
{ id: 'aromaWeight', name: 'aromaWeight', label: 'Фасовка отдушки, г', type: 'number', required: false },
|
||
{ id: 'moldPrice', name: 'moldPrice', label: 'Цена формы, руб', type: 'number', required: false },
|
||
{ id: 'box', name: 'box', label: 'Упаковка, руб', type: 'number', required: false },
|
||
{ id: 'markup', name: 'markup', label: 'Наценка, %', type: 'number', required: false },
|
||
];
|
||
|
||
/**
|
||
* Расчёт себестоимости свечи
|
||
* @param {Object} data - Данные для расчёта
|
||
* @returns {Object} Результаты расчёта
|
||
*/
|
||
function calculate(data) {
|
||
const {
|
||
weight = 0,
|
||
waxPrice = 0,
|
||
wickPrice = 0,
|
||
aromaPrice = 0,
|
||
aromaWeight = 1,
|
||
moldPrice = 0,
|
||
box = 0,
|
||
} = data;
|
||
|
||
const wax = (weight / 1000) * waxPrice;
|
||
const wick = wickPrice;
|
||
const aroma = ((weight * 0.08) / aromaWeight) * aromaPrice; // 8% отдушки для свечей
|
||
const mold = moldPrice / 50; // Амортизация формы на 50 свечей
|
||
const packaging = box;
|
||
|
||
const subtotal = wax + wick + aroma + mold + packaging;
|
||
const operational = subtotal * 0.05;
|
||
const total = subtotal + operational;
|
||
|
||
return {
|
||
wax: round(wax),
|
||
wick: round(wick),
|
||
aroma: round(aroma),
|
||
mold: round(mold),
|
||
packaging: round(packaging),
|
||
operational: round(operational),
|
||
total: round(total),
|
||
};
|
||
}
|
||
|
||
function round(val) {
|
||
return Math.round(val * 10) / 10;
|
||
}
|
||
|
||
/**
|
||
* Форматирует сообщение для Telegram
|
||
* @param {Object} data - Исходные данные
|
||
* @param {Object} result - Результаты расчёта
|
||
* @returns {string} Отформатированное сообщение
|
||
*/
|
||
function formatMessage(data, result) {
|
||
const {
|
||
candleName,
|
||
weight = 0,
|
||
box = 0,
|
||
markup = 0,
|
||
totalCost,
|
||
finalPrice,
|
||
pricePer100g,
|
||
} = data;
|
||
|
||
let text = `🕯️ <b>Расчёт свечи:</b> <i>${candleName}</i>\n\n`;
|
||
text += `⚖️ <b>Вес свечи:</b> ${weight} г\n\n`;
|
||
text += `📦 <b>Упаковка:</b> ${box} ₽\n\n`;
|
||
text += `💹 <b>Наценка:</b> ${markup}%\n\n`;
|
||
text += `📊 <b>Итоги расчёта:</b>\n`;
|
||
text += ` 💵 Себестоимость: ${Number(totalCost).toFixed(1)} ₽\n`;
|
||
text += ` 🎯 Итоговая цена с наценкой: ${Number(finalPrice).toFixed(1)} ₽\n`;
|
||
text += ` ⚗️ Цена за 100 г: ${Number(pricePer100g).toFixed(1)} ₽`;
|
||
|
||
return text;
|
||
}
|
||
|
||
/**
|
||
* Получить обязательные поля для валидации
|
||
* @returns {string[]} Массив имён обязательных полей
|
||
*/
|
||
function getRequiredFields() {
|
||
return fieldSchema.filter((f) => f.required).map((f) => f.name);
|
||
}
|
||
|
||
/**
|
||
* Получить числовые поля для валидации
|
||
* @returns {string[]} Массив имён числовых полей
|
||
*/
|
||
function getNumericFields() {
|
||
return fieldSchema.filter((f) => f.type === 'number').map((f) => f.name);
|
||
}
|
||
|
||
module.exports = {
|
||
id: 'candle',
|
||
name: 'Свеча',
|
||
fieldSchema,
|
||
calculate,
|
||
formatMessage,
|
||
getRequiredFields,
|
||
getNumericFields,
|
||
};
|
||
|