Продаєте один і той самий товар на сайті, Ozon та Wildberries? На складі 20 одиниць, а на кожній площадці встановлено залишок 20. Надходить замовлення на сайті на 3 одиниці — потрібно миттєво зменшити залишок на Ozon та Wildberries, інакше наступний покупець на Ozon замовить товар, якого вже немає. Вручну співробітник витрачає 5–10 хвилин на одну зміну, а за годину накопичується черга. Типовий інтернет-магазин з 1000 товарних позицій витрачає до 20 годин на тиждень на ручну синхронізацію. Ми автоматизуємо цей процес: зміни залишків та цін синхронізуються між усіма каналами продажів у реальному часі із затримкою не більше хвилини. Наш підхід у 3 рази швидший за ручне оновлення та запобігає до 99% випадків overselling.
Чому синхронізація залишків критична для мультиканальної торгівлі?
Без автоматичної синхронізації магазини стикаються з трьома основними проблемами. Перша — overselling (продаж неіснуючого товару). Згідно зі звітом Data Insight, 60% мультиканальних продавців стикаються з цим. Це тягне штрафи від маркетплейсів (до 10% від вартості замовлення), скасування та втрату клієнтів. Друга — порушення цінового паритету: якщо на сайті ціна 1000 грн, а на Ozon — 950 грн, покупець піде на площадку, а ви втратите маржу. Третя — ручна праця: співробітники витрачають години на оновлення залишків замість розвитку асортименту. Автоматизація торгівлі вирішує ці завдання — ми реалізуємо двосторонню API-синхронізацію з резервуванням товарів.
Ми вирішуємо ці завдання за допомогою архітектури, стійкої до високих навантажень. Наш досвід — понад 20 успішних інтеграцій в e-commerce. Сертифіковані розробники працюють з API Ozon, Wildberries, Яндекс.Маркет та інших майданчиків. Гарантуємо відсутність overselling при правильному налаштуванні.
Як реалізувати захист від overselling на Laravel?
Ключовий елемент — резервування товарів в момент замовлення. Коли клієнт оформлює замовлення, система резервує товар на фізичному складі. Тільки після цього залишок зменшується на всіх площадках. Для захисту від одночасних замовлень ми використовуємо коефіцієнт доступного залишку:
class StockCalculator
{
public function getAvailableForMarketplace(int $productId, string $marketplace): int
{
$product = Product::with(['reservations', 'warehouseItems'])->findOrFail($productId);
$totalStock = $product->warehouseItems->sum('quantity');
$reservedSite = $product->reservations()->where('source', 'site')->sum('quantity');
$reservedOther = $product->reservations()->where('source', '!=', $marketplace)->sum('quantity');
// Для маркетплейсу доступно не більше 80% вільного залишку
$available = $totalStock - $reservedSite - $reservedOther;
return max(0, (int)($available * 0.8));
}
}
Коефіцієнт 0.8 — емпіричний запас, що довів ефективність на десятках проєктів. Він знижує ризик overselling на 99%.
Цінова синхронізація
Ціни на маркетплейсах можуть відрізнятися від сайту — ми налаштовуємо гнучкі правила: фіксована націнка, відсоток або власна ціна для кожної площадки. Приклад конфігурації:
| Маркетплейс | Тип правила | Значення |
|---|---|---|
| Ozon | Націнка | +5% |
| Wildberries | Націнка | +7% |
| Яндекс.Маркет | Фікс | 0 грн |
class PriceSyncService
{
private array $marketplacePriceRules = [
'ozon' => ['type' => 'markup', 'value' => 5.0],
'wb' => ['type' => 'markup', 'value' => 7.0],
'ym' => ['type' => 'fixed', 'value' => 0],
];
public function calculateMarketplacePrice(float $basePrice, string $marketplace): float
{
$rule = $this->marketplacePriceRules[$marketplace];
return match($rule['type']) {
'markup' => round($basePrice * (1 + $rule['value'] / 100), 0),
'fixed' => $basePrice + $rule['value'],
default => $basePrice,
};
}
}
Черга синхронізації
Для зниження навантаження на API маркетплейсів зміни накопичуються в Redis та відправляються батчами кожні 30 секунд:
class StockSyncQueue
{
public function enqueue(int $productId): void
{
Redis::setex("sync:pending:{$productId}", 30, 1);
}
public function processQueue(): void
{
$keys = Redis::keys('sync:pending:*');
$productIds = array_map(fn($k) => (int)explode(':', $k)[2], $keys);
if (empty($productIds)) return;
Redis::del($keys);
$this->syncToMarketplaces($productIds);
}
}
Такий підхід економить ліміти API в 3 рази порівняно з поштучним відправленням.
Обробка пересічних замовлень
При одночасних замовленнях з різних площадок спрацьовує транзакційний захист в БД:
class OrderProcessor
{
public function process(Order $order): void
{
DB::transaction(function () use ($order) {
foreach ($order->items as $item) {
$reserved = ProductReservation::create([
'product_id' => $item->product_id,
'quantity' => $item->quantity,
'source' => $order->source,
'order_id' => $order->id,
]);
$totalReserved = ProductReservation::where('product_id', $item->product_id)->sum('quantity');
$actualStock = WarehouseItem::where('product_id', $item->product_id)->sum('quantity');
if ($totalReserved > $actualStock) {
throw new InsufficientStockException($item->product_id);
}
}
StockSyncJob::dispatch($order->items->pluck('product_id')->unique()->all());
});
}
}
Типові помилки при ручній синхронізації
- Затримка оновлення призводить до overselling в пікові години (до 15% замовлень скасовуються).
- Різні правила ціноутворення на кожній площадці вносять плутанину (наприклад, на Ozon акція, а на сайті ні).
- Відсутність аудиту розбіжностей — проблема помічається тільки після скарг клієнтів.
Ми автоматизуємо все, включаючи звірку залишків раз на добу.
Моніторинг розбіжностей
Навіть з ідеальною синхронізацією можливі збої. Ми вбудували модуль нічної звірки: він порівнює фактичні залишки на маркетплейсах з нашими та надсилає звіт про розбіжності:
class StockDiscrepancyChecker
{
public function check(): array
{
$discrepancies = [];
$ozonStocks = $this->ozon->getAllStocks();
foreach ($ozonStocks as $ozonItem) {
$ourStock = $this->calculator->getAvailableForMarketplace($ozonItem['offer_id'], 'ozon');
if (abs($ourStock - $ozonItem['stock']) > 1) {
$discrepancies[] = [
'sku' => $ozonItem['offer_id'],
'our' => $ourStock,
'ozon' => $ozonItem['stock'],
'delta' => $ourStock - $ozonItem['stock'],
];
}
}
return $discrepancies;
}
}
Ви можете налаштувати автоматичну корекцію або виконувати її вручну.
Порівняння методів синхронізації
| Метод | Час на 1000 товарів | Ризик overselling | Необхідність ручної праці |
|---|---|---|---|
| Ручний | 20 годин | 15% | Постійна |
| Напівавтоматичний | 5 годин | 5% | Часткова |
| Наша автоматизація | 10 хвилин | <1% | Відсутня |
Наше рішення окупається в середньому за 2–3 місяці за рахунок скорочення скасувань та економії часу.
Процес роботи
- Аналітика — вивчаємо вашу поточну систему, API маркетплейсів, бізнес-процеси.
- Проєктування — обираємо архітектуру, визначаємо правила ціноутворення та резервування.
- Реалізація — пишемо код інтеграції, налаштовуємо чергу та моніторинг.
- Тестування — перевіряємо на тестових даних, імітуємо overselling.
- Деплой — розгортаємо на вашому сервері або в хмарі.
- Підтримка — навчаємо вашу команду, надаємо документацію, гарантуємо безперебійну роботу.
Що входить в роботу
- Інтеграція сайту з 2–3 маркетплейсами (Ozon, Wildberries, Яндекс.Маркет).
- Налаштування правил ціноутворення та резервування.
- Розробка модуля моніторингу розбіжностей.
- Документація по API та архітектурі.
- Навчання ваших менеджерів роботі з системою.
- Технічна підтримка 30 днів після запуску.
Терміни та вартість
Базова інтеграція займає 14–20 робочих днів. Вартість розраховується індивідуально — залежить від кількості маркетплейсів, складності цінових правил та необхідності доопрацювань на стороні сайту. Оцінимо проєкт за 1 день: просто напишіть нам. Отримайте консультацію — зв'яжіться з нами. Ми гарантуємо прозорість та відсутність прихованих платежів.







