Pre-Order System for E-Commerce

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Showing 1 of 1 servicesAll 2065 services
Pre-Order System for E-Commerce
Medium
~3-5 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Development of Pre-Order System for E-Commerce

Pre-order is buyer commitment to purchase goods before arrival. Technically it's intersection of several systems: inventory, payments, communications, and expectation management. Poorly implemented pre-order leads to conflicts — customer paid but store can't fulfill obligation or forgets when promised.

Pre-Order Scenarios

Pre-orders differ fundamentally in business logic:

Full payment now — customer pays immediately, goods ship when arrives. Suits products with known delivery date (new electronics, books).

Partial prepayment — deposit 20–50%, balance on shipment. Requires two-stage payment. More complex technically, lowers buyer barrier.

No payment (reservation) — customer leaves request, money charged on arrival or manager contacts manually. Weakest conversion.

Group pre-order — goods produced/ordered only when minimum quantity reached. Crowdfunding mechanics.

Data Schema

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 = unlimited
    min_quantity    INTEGER,             -- for group pre-order
    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 on fulfillment
    created_at      TIMESTAMP NOT NULL DEFAULT NOW()
);

Payment: Two-Stage Scenario

In deposit mode — payment in two steps:

Step 1: Deposit on pre-order placement

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' => "Pre-order #{$preorder->id}: deposit",
            'metadata'    => ['preorder_id' => $preorder->id, 'type' => 'deposit'],
        ]);

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

        return $payment;
    }
}

Step 2: Balance on goods arrival

When goods arrive, automatic charge attempt launched. If card no longer valid — email sent with new payment link.

Quantity Limit and Queue

For limited pre-orders, need atomic limit check:

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;

If row didn't return — limit exhausted. User offered waitlist.

Waitlist

Separate table for those who didn't make it:

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)
);

On spot freed (pre-order cancellation) — automatic notification to first N in queue with limited-time offer.

Fulfillment on Goods Arrival

When goods arrive, manager starts fulfillment process:

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) {
                // Check stock
                $reserved = $this->stockService->reserve(
                    $preorder->variant_id,
                    $preorder->qty
                );

                if (!$reserved) {
                    return; // Stock insufficient, skip
                }

                // Create real order
                $order = $this->orderFactory->fromPreorder($preorder);

                // Charge balance if needed
                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());
    }
}

Customer Communications

Pre-order is a promise, customer must constantly understand status:

Event Channel Content
Placement Email Confirmation, details, expected date
Date change Email + SMS New date, reason for delay
Stock arrived Email + Push Shipment starting notification
Order created Email Order number, tracking
Campaign cancelled Email Refund instruction

Templates editable in admin. Delivery date always shows "approximately: April 2025" not exact date if unsure.

Storefront Display

Product card in pre-order mode:

  • "Pre-Order" button instead of "Add to Cart"
  • Expected delivery date below button
  • Taken slots counter (if limited): "Reserved 47 of 100"
  • Deficit indicator: "12 slots left"
  • Policy block about pre-order and returns

Implementation Timeline

  • Basic system: placement + full payment + notifications: 4–6 days
  • Two-stage payment (deposit + balance): +2–3 days
  • Group pre-order with minimum threshold: +2 days
  • Waitlist with auto-notifications: +1–2 days
  • Admin campaign panel: +2–3 days

Full system with multiple modes and analytics: 2–3 weeks.