Розробка системи передзамовлень для інтернет-магазину

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка системи передзамовлень для інтернет-магазину
Середня
~3-5 робочих днів
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка системи передзаказів для E-Commerce

Предзаказ — це зобов'язання покупця купити товар до його появи на складі. Технічно це перетин кількох систем: інвентарю, платежів, комунікацій та управління очікуванням. Погано реалізований передзаказ приводить до конфліктів — покупатель заплатив, а магазин не може виконати зобов'язання або забуває, коли обіцяв.

Сценарії передзаказу

Передзакази бувають принципово різними за бізнес-логіці:

Повна оплата сейчас — покупатель платить відразу, товар відправляється коли поступить. Підходить для товарів з відомою датою поставки (нові моделі електроніки, книги).

Частична передоплата — депозит 20–50%, залишок — при відправці. Потребує двохетапного платежу. Складніше технічно, знижує барʼєр для покупця.

Без оплати (бронювання місця) — покупатель залишає заявку, гроші списуються при поступленні або менеджер зв'язується вручну. Найслабший варіант за конверсією.

Груповий передзаказ — товар виробляється/замовляється тільки при досягненні мінімальної кількості. Crowdfunding-механіка.

Схема даних

CREATE TABLE preorder_campaigns (
    id              BIGSERIAL PRIMARY KEY,
    product_id      BIGINT NOT NULL REFERENCES products(id),
    name            VARCHAR(255) NOT NULL,
    status          VARCHAR(50) NOT NULL DEFAULT 'active',
                    -- active | paused | fulfilled | cancelled
    payment_mode    VARCHAR(50) NOT NULL DEFAULT 'full',
                    -- full | deposit | free
    deposit_percent NUMERIC(5,2),
    expected_date   DATE,
    max_quantity    INTEGER,              -- NULL = без обмеження
    min_quantity    INTEGER,             -- для групового передзаказу
    current_count   INTEGER NOT NULL DEFAULT 0,
    closes_at       TIMESTAMP,
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

CREATE TABLE preorders (
    id              BIGSERIAL PRIMARY KEY,
    campaign_id     BIGINT NOT NULL REFERENCES preorder_campaigns(id),
    user_id         BIGINT REFERENCES users(id),
    email           VARCHAR(255) NOT NULL,
    variant_id      BIGINT NOT NULL REFERENCES product_variants(id),
    qty             INTEGER NOT NULL DEFAULT 1,
    unit_price      NUMERIC(12,2) NOT NULL,
    deposit_paid    NUMERIC(12,2) NOT NULL DEFAULT 0,
    total_paid      NUMERIC(12,2) NOT NULL DEFAULT 0,
    status          VARCHAR(50) NOT NULL DEFAULT 'pending',
                    -- pending | deposit_paid | fully_paid | fulfilled | cancelled | refunded
    expected_date   DATE,
    notified_at     TIMESTAMP,
    order_id        BIGINT REFERENCES orders(id),   -- створюється при виконанні
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

Прием оплаты: двухэтапний сценарій

При режимі deposit — платіж у два кроки:

Крок 1: Депозит при оформленні передзаказу

class PreorderCheckout
{
    public function processDeposit(Preorder $preorder, PaymentMethod $method): Payment
    {
        $depositAmount = $preorder->unit_price * $preorder->qty
            * ($preorder->campaign->deposit_percent / 100);

        $payment = $this->gateway->charge([
            'amount'      => $depositAmount,
            'currency'    => 'RUB',
            'description' => "Передзаказ #{$preorder->id}: депозит",
            'metadata'    => ['preorder_id' => $preorder->id, 'type' => 'deposit'],
        ]);

        $preorder->update([
            'deposit_paid' => $depositAmount,
            'status'       => 'deposit_paid',
        ]);

        return $payment;
    }
}

Крок 2: Залишок при поступленні товару

Коли товар поступає на склад, запускається автоматична спроба списання залишку. Якщо карта вже не актуальна — покупателю йде лист з новою ссилкою для оплати.

Обмеження кількості та черга

Для лімітованих передзаказів потрібна атомарна перевірка ліміту:

UPDATE preorder_campaigns
SET current_count = current_count + :qty
WHERE id = :campaign_id
  AND (max_quantity IS NULL OR current_count + :qty <= max_quantity)
  AND status = 'active'
RETURNING id, current_count;

Якщо рядок не повернувся — ліміт вичерпан. Користувачу пропонується стати у лист ожидання.

Лист ожідання

Окрема таблиця для тих, хто не встиг:

CREATE TABLE waitlist_entries (
    id          BIGSERIAL PRIMARY KEY,
    campaign_id BIGINT NOT NULL REFERENCES preorder_campaigns(id),
    email       VARCHAR(255) NOT NULL,
    variant_id  BIGINT REFERENCES product_variants(id),
    notified    BOOLEAN NOT NULL DEFAULT false,
    created_at  TIMESTAMP NOT NULL DEFAULT NOW(),
    UNIQUE (campaign_id, email, variant_id)
);

При звільненні місця (скасування передзаказу) — автоматичне сповіщення першим N у черзі з обмеженою по часу пропозицією.

Виконання передзаказів при поступленні товару

Коли товар приходить на склад, менеджер запускає процес виконання:

class PreorderFulfillmentService
{
    public function fulfill(PreorderCampaign $campaign): FulfillmentResult
    {
        $preorders = $campaign->preorders()
            ->where('status', 'deposit_paid')
            ->orWhere('status', 'fully_paid')
            ->orderBy('created_at')  // FIFO
            ->get();

        $fulfilled = 0;

        foreach ($preorders as $preorder) {
            DB::transaction(function () use ($preorder, &$fulfilled) {
                // Перевіряємо наявність остатка
                $reserved = $this->stockService->reserve(
                    $preorder->variant_id,
                    $preorder->qty
                );

                if (!$reserved) {
                    return; // Остатка не хватає, пропускаємо
                }

                // Створюємо реальний заказ
                $order = $this->orderFactory->fromPreorder($preorder);

                // Списуємо остаток по доплаті якщо потрібно
                if ($preorder->needsBalancePayment()) {
                    $this->chargeBalance($preorder);
                }

                $preorder->update(['status' => 'fulfilled', 'order_id' => $order->id]);
                $fulfilled++;

                PreorderFulfilled::dispatch($preorder, $order);
            });
        }

        return new FulfillmentResult($fulfilled, $preorders->count());
    }
}

Комунікації з покупцями

Передзаказ — це обіцянка, та покупатель має постійно розуміти статус:

Подія Канал Вміст
Оформлення Email Підтвердження, деталі, очікувана дата
Зміна дати Email + SMS Нова дата, причина затримки
Товар поступив Email + Push Сповіщення про початок відправки
Заказ створений Email Номер замовлення, трек
Скасування кампанії Email Інструкція по поверненню

Шаблони сповіщень — окрема сутність, редагована в адмінці. Дата поставки в листах завжди відображається у форматі "орієнтовно: квітень 2025" а не точною датою, якщо впевненості немає.

Відображення на вітрині

Карточка товару у режимі передзаказу:

  • Кнопка "Передзаказати" замість "В кошик"
  • Очікувана дата поставки під кнопкою
  • Лічильник займаних місць (якщо ліміт): "Забронировано 47 з 100"
  • Індикатор дефіциту: "Залишилось 12 місць"
  • Інформаційний блок про політику передзаказів та повернень

Сроки реалізації

  • Базова система: оформлення + повна оплата + сповіщення: 4–6 днів
  • Двохетапна оплата (депозит + залишок): +2–3 дня
  • Груповий передзаказ з мінімальним порогом: +2 дня
  • Лист очидання з автосповіщеннями: +1–2 дня
  • Панель управління кампаніями в адмінці: +2–3 дня

Повна система з кількома режимами та аналітикою: 2–3 тижня.