DoSoapCalc/frontend/lib/calculators/soap.ts

77 lines
3.1 KiB
TypeScript
Raw 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.

// lib/calculators/soap.ts
// Калькулятор мыла для frontend
import type { Calculator, CalculatorField, CalculationResult } from '@/types/calculator';
const fieldSchema: CalculatorField[] = [
{ id: 'soapName', name: 'soapName', label: 'Название мыла', type: 'text', required: true },
{ id: 'weight', name: 'weight', label: 'Вес мыла, г', type: 'number', required: true },
{ id: 'basePrice', name: 'basePrice', label: 'Цена основы, руб', type: 'number', required: false },
{ id: 'aromaPrice', name: 'aromaPrice', label: 'Цена отдушки, руб', type: 'number', required: false },
{ id: 'aromaWeight', name: 'aromaWeight', label: 'Фасовка отдушки, г', type: 'number', required: false },
{ id: 'pigmentPrice', name: 'pigmentPrice', label: 'Цена пигмента, руб', type: 'number', required: false },
{ id: 'pigmentWeight', name: 'pigmentWeight', label: 'Фасовка пигмента, г', type: 'number', required: false },
{ id: 'moldPrice', name: 'moldPrice', label: 'Цена формы, руб', type: 'number', required: false },
{ id: 'box', name: 'box', label: 'Пакет/коробка, руб', type: 'number', required: false, group: 'packaging' },
{ id: 'filler', name: 'filler', label: 'Наполнитель, руб', type: 'number', required: false, group: 'packaging' },
{ id: 'ribbon', name: 'ribbon', label: 'Лента, руб', type: 'number', required: false, group: 'packaging' },
{ id: 'labelValue', name: 'labelValue', label: 'Наклейка, руб', type: 'number', required: false, group: 'packaging' },
{ id: 'markup', name: 'markup', label: 'Наценка, %', type: 'number', required: false },
];
function round(val: number): number {
return Math.round(val * 10) / 10;
}
function calculate(data: Record<string, any>): CalculationResult {
const {
weight = 0,
basePrice = 0,
aromaPrice = 0,
aromaWeight = 1,
pigmentPrice = 0,
pigmentWeight = 1,
moldPrice = 0,
packaging = { box: 0, filler: 0, ribbon: 0, label: 0 },
} = data;
const base = (weight / 1000) * basePrice;
const aroma = ((weight * 0.01) / aromaWeight) * aromaPrice;
const pigment = ((weight * 0.005) / pigmentWeight) * pigmentPrice;
const mold = moldPrice / 100;
const packagingCost = (packaging.box || 0) + (packaging.filler || 0) + (packaging.ribbon || 0) + (packaging.label || 0);
const subtotal = base + aroma + pigment + mold + packagingCost;
const operational = subtotal * 0.05;
const total = subtotal + operational;
return {
base: round(base),
aroma: round(aroma),
pigment: round(pigment),
mold: round(mold),
packaging: round(packagingCost),
operational: round(operational),
total: round(total),
};
}
function getRequiredFields(): string[] {
return fieldSchema.filter((f) => f.required).map((f) => f.name);
}
function getNumericFields(): string[] {
return fieldSchema.filter((f) => f.type === 'number').map((f) => f.name);
}
const soapCalculator: Calculator = {
id: 'soap',
name: 'Мыло',
fieldSchema,
calculate,
getRequiredFields,
getNumericFields,
};
export default soapCalculator;