Реалізація конфігуратора продукту на веб-сайті
Конфігуратор продукту — це інтерфейс, у якому покупець збирає фінальний варіант товару з набору параметрів: матеріал, розмір, колір, комплектація, гравіювання. На відміну від простого вибору варіанта (S/M/L), конфігуратор працює з комбінаторикою: кількість варіантів може досягати мільйонів, і зберігати кожний як окремий SKU неможливо. Підсумкова ціна та склад обчислюються динамічно.
Архітектурний вибір: SKU vs динамічна конфігурація
Табличні варіанти (SKU) підходять, коли комбінацій до кількох тисяч, і кожна має свій залишок на складі. Стандартний підхід для одягу.
Динамічна конфігурація потрібна, коли:
- Кількість можливих комбінацій > 10 000
- Кожен параметр незалежно впливає на ціну
- Виробництво під замовлення (немає готового складу)
- Потрібна візуалізація результату в реальному часі
Схема даних конфігуратора
CREATE TABLE configurator_products (
id BIGSERIAL PRIMARY KEY,
product_id BIGINT NOT NULL REFERENCES products(id),
name VARCHAR(255) NOT NULL,
base_price NUMERIC(12,2) NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true
);
CREATE TABLE configurator_option_groups (
id BIGSERIAL PRIMARY KEY,
configurator_id BIGINT NOT NULL REFERENCES configurator_products(id),
name VARCHAR(255) NOT NULL, -- "Матеріал", "Колір", "Гравіювання"
type VARCHAR(50) NOT NULL,
-- select | radio | checkbox | text | number | color
is_required BOOLEAN NOT NULL DEFAULT true,
sort_order INTEGER NOT NULL DEFAULT 0
);
CREATE TABLE configurator_options (
id BIGSERIAL PRIMARY KEY,
group_id BIGINT NOT NULL REFERENCES configurator_option_groups(id),
label VARCHAR(255) NOT NULL,
value VARCHAR(255) NOT NULL,
price_modifier NUMERIC(12,2) NOT NULL DEFAULT 0, -- абсолютна надбавка
price_modifier_pct NUMERIC(5,2) NOT NULL DEFAULT 0, -- відсоткова надбавка
modifier_type VARCHAR(20) NOT NULL DEFAULT 'add', -- add | multiply | fixed
sku_suffix VARCHAR(50), -- для формування SKU
is_available BOOLEAN NOT NULL DEFAULT true,
image_url VARCHAR(500), -- попередній перегляд опції
sort_order INTEGER NOT NULL DEFAULT 0
);
-- Правила залежності між опціями
CREATE TABLE configurator_rules (
id BIGSERIAL PRIMARY KEY,
configurator_id BIGINT NOT NULL REFERENCES configurator_products(id),
rule_type VARCHAR(50) NOT NULL, -- requires | excludes | enables
if_option_id BIGINT NOT NULL REFERENCES configurator_options(id),
then_option_id BIGINT NOT NULL REFERENCES configurator_options(id)
);
Обчислення ціни
Ціна конфігурації обчислюється на сервері, а не на клієнті:
class ConfiguratorPriceCalculator
{
public function calculate(
ConfiguratorProduct $configurator,
array $selectedOptions // [group_id => option_id | value]
): PriceBreakdown
{
$base = $configurator->base_price;
$breakdown = [['label' => 'Базова ціна', 'amount' => $base]];
$total = $base;
foreach ($selectedOptions as $groupId => $selection) {
$group = $configurator->optionGroups->find($groupId);
if ($group->type === 'text' || $group->type === 'number') {
// Для вільного введення — фіксована надбавка за групу
$modifier = $group->text_price_modifier ?? 0;
} else {
$option = ConfiguratorOption::findOrFail($selection);
$modifier = $this->resolveModifier($option, $total);
}
if ($modifier != 0) {
$breakdown[] = [
'label' => $group->name . ($group->type !== 'text' ? ': ' . $option->label : ''),
'amount' => $modifier,
];
$total += $modifier;
}
}
return new PriceBreakdown($total, $breakdown);
}
private function resolveModifier(ConfiguratorOption $option, float $currentTotal): float
{
return match($option->modifier_type) {
'add' => $option->price_modifier,
'multiply' => $currentTotal * ($option->price_modifier_pct / 100),
'fixed' => $option->price_modifier - $currentTotal,
};
}
}
Клієнт показує ціну попередньо (з JS-розрахунку), але при додаванні в кошик ціна завжди перераховується на сервері. Довіряти клієнтському розрахунку у фінансовому контексті неможливо.
Правила залежності
Деякі опції взаємно виключають одна одну або вимагають вибору іншої опції. Правила перевіряються і на клієнті (UX), і на сервері (валідація):
class ConfiguratorRuleEngine
{
public function validate(ConfiguratorProduct $configurator, array $selected): ValidationResult
{
$errors = [];
foreach ($configurator->rules as $rule) {
$ifSelected = in_array($rule->if_option_id, $selected);
$thenSelected = in_array($rule->then_option_id, $selected);
match($rule->rule_type) {
'requires' => $ifSelected && !$thenSelected
? $errors[] = "Опція вимагає вибору: {$rule->thenOption->label}"
: null,
'excludes' => $ifSelected && $thenSelected
? $errors[] = "Несумісні опції: {$rule->thenOption->label}"
: null,
'enables' => !$ifSelected
? $this->disableOption($rule->then_option_id)
: null,
};
}
return new ValidationResult(empty($errors), $errors);
}
}
Формування SKU конфігурації
Для виробництва важливо мати детермінований код конфігурації:
class ConfigurationSkuBuilder
{
public function build(ConfiguratorProduct $configurator, array $selected): string
{
$parts = [$configurator->product->sku];
$sortedOptions = collect($selected)
->sortKeys()
->map(fn($optionId, $groupId) =>
ConfiguratorOption::find($optionId)?->sku_suffix ?? $optionId
);
return implode('-', array_merge($parts, $sortedOptions->all()));
// Приклад: CHAIR-BLK-LEATH-ARMB-CUST
}
}
API для фронтенда
Конфігуратор працює через AJAX. Мінімальний набір кінцевих точок:
GET /api/configurators/{id} — повна схема конфігуратора
POST /api/configurators/{id}/price — перерахунок ціни за вибором
POST /api/configurators/{id}/validate — валідація набору опцій
POST /api/cart/add-configuration — додавання конфігурації в кошик
Запит перерахунку ціни:
POST /api/configurators/5/price
{
"selected": {
"1": 12,
"2": 7,
"3": "Іван Іванов"
}
}
Відповідь:
{
"total": 4850.00,
"breakdown": [
{ "label": "Базова ціна", "amount": 3500.00 },
{ "label": "Матеріал: Натуральна шкіра", "amount": 1200.00 },
{ "label": "Колір: Чорний", "amount": 0 },
{ "label": "Гравіювання", "amount": 150.00 }
]
}
Збереження конфігурації в кошику
Конфігурація зберігається як JSON у позиції кошика:
ALTER TABLE cart_items ADD COLUMN configuration JSONB;
ALTER TABLE order_items ADD COLUMN configuration JSONB;
ALTER TABLE order_items ADD COLUMN configuration_sku VARCHAR(255);
{
"configurator_id": 5,
"groups": {
"1": { "option_id": 12, "label": "Натуральна шкіра" },
"2": { "option_id": 7, "label": "Чорний" },
"3": { "type": "text", "value": "Іван Іванов" }
},
"sku": "CHAIR-LEATH-BLK-CUST",
"price_at_add": 4850.00
}
При додаванні конфігурації в кошик ціна перераховується на сервері та фіксується. Зміна прайсу не впливає на вже додані конфігурації.
Адміністративний інтерфейс
Менеджер повинен мати можливість:
- Створювати та редагувати конфігуратори без програміста
- Керувати порядком груп та опцій
- Встановлювати правила залежності через UI (не SQL)
- Переглядати конфігуратор перед публікацією
Терміни реалізації
- Базова схема + API перерахунку ціни + додавання в кошик: 5–7 днів
- Правила залежності (requires/excludes): 2–3 дні
- Адміністративний інтерфейс для управління конфігуратором: 3–4 дні
- Візуальний попередній перегляд (зміна зображення при виборі опції): 2–3 дні
- Інтеграція з системою виробничих завдань: +3–5 днів
Типовий проект: 2–4 тижні залежно від складності правил та вимог до візуалізації.







