194 lines
6.9 KiB
Markdown
194 lines
6.9 KiB
Markdown
# Руководство по добавлению нового калькулятора
|
||
|
||
Это руководство описывает, как добавить новый калькулятор в систему DoSoapCalc.
|
||
|
||
## Архитектура
|
||
|
||
Система использует модульную архитектуру с регистрацией калькуляторов:
|
||
- Каждый калькулятор — отдельный модуль с формулой, схемой полей и шаблоном сообщения
|
||
- Общие компоненты автоматически генерируют формы и обрабатывают запросы
|
||
- Динамическая маршрутизация на основе типа калькулятора
|
||
|
||
## Шаги добавления нового калькулятора
|
||
|
||
### 1. Создание модуля калькулятора на Backend
|
||
|
||
Создайте файл `backend/calculators/[calculator-name].js` (например, `candle.js`).
|
||
|
||
#### Структура модуля:
|
||
|
||
```javascript
|
||
// calculators/[calculator-name].js
|
||
const fieldSchema = [
|
||
{ id: 'itemName', name: 'itemName', label: 'Название изделия', type: 'text', required: true },
|
||
{ id: 'weight', name: 'weight', label: 'Вес, г', type: 'number', required: true },
|
||
// ... другие поля
|
||
];
|
||
|
||
function calculate(data) {
|
||
// Ваша формула расчёта
|
||
const total = /* вычисления */;
|
||
return {
|
||
// промежуточные результаты
|
||
total: round(total),
|
||
};
|
||
}
|
||
|
||
function formatMessage(data, result) {
|
||
// Шаблон сообщения для Telegram
|
||
let text = `...`;
|
||
return text;
|
||
}
|
||
|
||
function getRequiredFields() {
|
||
return fieldSchema.filter((f) => f.required).map((f) => f.name);
|
||
}
|
||
|
||
function getNumericFields() {
|
||
return fieldSchema.filter((f) => f.type === 'number').map((f) => f.name);
|
||
}
|
||
|
||
module.exports = {
|
||
id: 'calculator-name', // уникальный ID
|
||
name: 'Название калькулятора',
|
||
fieldSchema,
|
||
calculate,
|
||
formatMessage,
|
||
getRequiredFields,
|
||
getNumericFields,
|
||
};
|
||
```
|
||
|
||
#### Пример поля:
|
||
|
||
```javascript
|
||
{
|
||
id: 'fieldId', // уникальный ID поля
|
||
name: 'fieldName', // имя поля (используется в данных)
|
||
label: 'Название поля', // метка для пользователя
|
||
type: 'text' | 'number', // тип поля
|
||
required: true | false, // обязательное ли поле
|
||
group: 'packaging', // (опционально) группа для группировки полей
|
||
}
|
||
```
|
||
|
||
### 2. Регистрация на Backend
|
||
|
||
Откройте `backend/calculators/index.js` и добавьте калькулятор:
|
||
|
||
```javascript
|
||
const newCalculator = require('./[calculator-name]');
|
||
|
||
const calculators = {
|
||
soap: soapCalculator,
|
||
'[calculator-name]': newCalculator, // добавьте здесь
|
||
};
|
||
```
|
||
|
||
### 3. Создание модуля калькулятора на Frontend
|
||
|
||
Создайте файл `frontend/lib/calculators/[calculator-name].ts`.
|
||
|
||
#### Структура модуля:
|
||
|
||
```typescript
|
||
// lib/calculators/[calculator-name].ts
|
||
import type { Calculator, CalculatorField, CalculationResult } from '@/types/calculator';
|
||
|
||
const fieldSchema: CalculatorField[] = [
|
||
{ id: 'itemName', name: 'itemName', label: 'Название изделия', type: 'text', required: true },
|
||
// ... другие поля (синхронно с backend!)
|
||
];
|
||
|
||
function calculate(data: Record<string, any>): CalculationResult {
|
||
// Та же формула, что и на backend
|
||
return {
|
||
total: round(total),
|
||
};
|
||
}
|
||
|
||
const newCalculator: Calculator = {
|
||
id: '[calculator-name]',
|
||
name: 'Название калькулятора',
|
||
fieldSchema,
|
||
calculate,
|
||
getRequiredFields: () => fieldSchema.filter((f) => f.required).map((f) => f.name),
|
||
getNumericFields: () => fieldSchema.filter((f) => f.type === 'number').map((f) => f.name),
|
||
};
|
||
|
||
export default newCalculator;
|
||
```
|
||
|
||
**Важно:** Схема полей и формула должны совпадать с backend!
|
||
|
||
### 4. Регистрация на Frontend
|
||
|
||
Откройте `frontend/lib/calculators/index.ts` и добавьте:
|
||
|
||
```typescript
|
||
import newCalculator from './[calculator-name]';
|
||
|
||
const calculators: Record<string, Calculator> = {
|
||
soap: soapCalculator,
|
||
'[calculator-name]': newCalculator, // добавьте здесь
|
||
};
|
||
```
|
||
|
||
### 5. Проверка работы
|
||
|
||
1. Перезапустите backend: `node bot.js`
|
||
2. Пересоберите frontend: `npm run build`
|
||
3. Откройте в браузере: `/[calculator-name]?chat_id=YOUR_CHAT_ID`
|
||
|
||
## Примеры
|
||
|
||
### Простой калькулятор (только базовые поля)
|
||
|
||
См. файлы:
|
||
- `backend/calculators/candle.js` - пример калькулятора свечей
|
||
- `frontend/lib/calculators/candle.ts` - frontend версия
|
||
|
||
### Калькулятор с группированными полями
|
||
|
||
Для группировки полей используйте параметр `group`:
|
||
|
||
```javascript
|
||
{ id: 'box', name: 'box', label: 'Пакет', type: 'number', group: 'packaging' },
|
||
{ id: 'ribbon', name: 'ribbon', label: 'Лента', type: 'number', group: 'packaging' },
|
||
```
|
||
|
||
Поля с одинаковой группой будут автоматически сгруппированы в форме.
|
||
|
||
## Советы
|
||
|
||
1. **Синхронизация:** Всегда поддерживайте синхронизацию между backend и frontend схемами
|
||
2. **Валидация:** Используйте `required: true` для обязательных полей
|
||
3. **Форматирование:** В `formatMessage` используйте HTML для форматирования (поддерживается Telegram)
|
||
4. **Округление:** Используйте функцию `round()` для округления результатов
|
||
|
||
## Структура файлов
|
||
|
||
```
|
||
backend/
|
||
├── calculators/
|
||
│ ├── index.js # Регистрация калькуляторов
|
||
│ ├── soap.js # Пример: калькулятор мыла
|
||
│ └── [new-calculator].js # Ваш новый калькулятор
|
||
|
||
frontend/
|
||
├── lib/
|
||
│ └── calculators/
|
||
│ ├── index.ts # Регистрация калькуляторов
|
||
│ ├── soap.ts # Пример: калькулятор мыла
|
||
│ └── [new-calculator].ts # Ваш новый калькулятор
|
||
```
|
||
|
||
## Что дальше?
|
||
|
||
После добавления калькулятора:
|
||
1. Протестируйте расчёты вручную
|
||
2. Проверьте отправку в Telegram
|
||
3. Убедитесь, что валидация работает корректно
|
||
4. Добавьте обработку специфичных данных (если нужно)
|
||
|