DoSoapCalc/frontend/calculators/candles/config.ts
DosAi 02c7520c90 Refactor: Modular calculator architecture
Created modular system for calculators, added soap and candles calculators, universal components, updated backend
2025-11-02 15:45:07 +03:00

247 lines
7.5 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Конфигурация калькулятора свечей
import { CalculatorConfig } from '@/lib/calculator-types';
import { calculateCandleStep, calculateCandleSubtotal, round } from './calc';
export const candlesCalculatorConfig: CalculatorConfig = {
id: 'candles',
name: 'Калькулятор свечей',
description: 'Расчет себестоимости свечей ручной работы',
icon: '🕯️',
fields: [
{
id: 'candleName',
type: 'text',
label: 'Название свечи',
placeholder: 'Введите название',
defaultValue: '',
gridCols: 1,
required: false,
},
{
id: 'photo',
type: 'file',
label: 'Фото свечи (необязательно)',
accept: 'image/*',
gridCols: 1,
required: false,
},
{
id: 'waxWeight',
type: 'number',
label: 'Вес воска, г',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'wax',
showStepAfter: 'wax',
},
{
id: 'waxPrice',
type: 'number',
label: 'Цена воска за 1 кг, руб',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'wax',
},
{
id: 'wickCount',
type: 'number',
label: 'Количество фитилей',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'wick',
showStepAfter: 'wick',
},
{
id: 'wickPrice',
type: 'number',
label: 'Цена одного фитиля, руб',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'wick',
},
{
id: 'fragrancePrice',
type: 'number',
label: 'Цена отдушки, руб',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'fragrance',
showStepAfter: 'fragrance',
},
{
id: 'fragranceWeight',
type: 'number',
label: 'Фасовка отдушки, г',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'fragrance',
},
{
id: 'dyePrice',
type: 'number',
label: 'Цена красителя, руб',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'dye',
showStepAfter: 'dye',
},
{
id: 'dyeWeight',
type: 'number',
label: 'Фасовка красителя, г',
defaultValue: '',
gridCols: 2,
required: false,
groupName: 'dye',
},
{
id: 'moldPrice',
type: 'number',
label: 'Стоимость формы/банки, руб',
defaultValue: '',
gridCols: 1,
required: false,
groupName: 'mold',
showStepAfter: 'mold',
},
{
id: 'packaging',
type: 'number',
label: 'Упаковка, руб',
defaultValue: '',
gridCols: 1,
required: false,
groupName: 'packaging',
showStepAfter: 'packaging',
},
{
id: 'markup',
type: 'number',
label: 'Наценка, %',
defaultValue: '',
gridCols: 2,
required: false,
},
],
calculationSteps: [
{
id: 'wax',
name: 'Себестоимость воска',
formula: (values) => round(calculateCandleStep('wax', values)),
formulaDescription: '(весоска / 1000) * ценаоска',
},
{
id: 'wick',
name: 'Себестоимость фитилей',
formula: (values) => round(calculateCandleStep('wick', values)),
formulaDescription: оличество_фитилей * цена_фитиля',
},
{
id: 'fragrance',
name: 'Себестоимость отдушки (10 %)',
formula: (values) => round(calculateCandleStep('fragrance', values)),
formulaDescription: '((весоска * 0.10) / фасовка_отдушки) * цена_отдушки',
},
{
id: 'dye',
name: 'Себестоимость красителя (1 %)',
formula: (values) => round(calculateCandleStep('dye', values)),
formulaDescription: '((весоска * 0.01) / фасовкарасителя) * ценарасителя',
},
{
id: 'mold',
name: 'Стоимость формы/банки',
formula: (values) => {
const moldPrice = values.moldPrice || 0;
// Предположим, форма рассчитана на 100 использований
return round(moldPrice / 100);
},
formulaDescription: 'стоимость_формы / 100',
},
{
id: 'packaging',
name: 'Стоимость упаковки',
formula: (values) => {
const packaging = values.packaging || 0;
return round(packaging);
},
formulaDescription: 'стоимость_упаковки',
},
],
subtotals: [
{
id: 'operational',
name: 'Операционные расходы (5 %)',
formula: (values, steps) => round(calculateCandleSubtotal('operational', values, steps)),
formulaDescription: '(воск + фитили + отдушка + краситель + форма + упаковка) * 0.05',
},
{
id: 'total',
name: 'Итого себестоимость',
formula: (values, steps) => round(calculateCandleSubtotal('total', values, steps)),
highlight: true,
formulaDescription: 'воск + фитили + отдушка + краситель + форма + упаковка + операционные',
},
],
additionalCalculations: [
{
id: 'finalPrice',
name: 'Итоговая цена с наценкой',
formula: (values, steps, subtotals) => {
const total = subtotals.total || 0;
const markup = values.markup || 0;
return round(total * (1 + markup / 100));
},
formulaDescription: 'итого_себестоимость * (1 + наценка / 100)',
},
{
id: 'pricePer100g',
name: 'Цена за 100 г',
formula: (values, steps, subtotals, additional) => {
const weight = values.waxWeight || 0;
const finalPrice = additional?.finalPrice || 0;
if (weight > 0) {
return round((finalPrice / weight) * 100);
}
return 0;
},
formulaDescription: '(итоговая_цена / весоска) * 100',
},
],
formatTelegramMessage: (values, steps, subtotals, additional) => {
const candleName = values.candleName || 'Без названия';
const waxWeight = values.waxWeight || 0;
const wickCount = values.wickCount || 0;
const packaging = values.packaging || 0;
const markup = values.markup || 0;
const totalCost = subtotals.total || 0;
const finalPrice = additional?.finalPrice || 0;
const pricePer100g = additional?.pricePer100g || 0;
let text = `🕯️ <b>Расчёт свечи:</b> <i>${candleName}</i>\n\n`;
text += `⚖️ <b>Вес воска:</b> ${waxWeight} г\n`;
text += `🕯️ <b>Количество фитилей:</b> ${wickCount} шт\n`;
text += `📦 <b>Упаковка:</b> ${packaging}\n\n`;
text += `💹 <b>Наценка:</b> ${markup}%\n\n`;
text += `📊 <b>Итоги расчёта:</b>\n`;
text += ` 💵 Себестоимость: ${totalCost.toFixed(1)}\n`;
text += ` 🎯 Итоговая цена с наценкой: ${finalPrice.toFixed(1)}\n`;
text += ` ⚗️ Цена за 100 г: ${pricePer100g.toFixed(1)}`;
return text;
},
};