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

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, 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

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

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

Сценарии предзаказа

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

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

Частичная предоплата — депозит 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 недели.