← усі кейси
E-commerce з власним складом E-commerce / Маркетплейси ·

Один майстер цін на вісім вітрин: ціни, залишки й картки без ручної роботи

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

  • Вісім вітрин отримують ціни з одного джерела двічі на добу, зі знижками як у магазині
  • Залишки зі складу розходяться по всіх майданчиках кожні десять хвилин
  • 3 710 карток товару, яких CRM не бачила, створено автоматично; каталог виріс у півтора раза
  • Записується лише різниця: прогін без змін не робить у магазині жодного запису
Python 3.12FastAPIAPSchedulerRedisDocker Compose

Коли магазин один, ціна живе в одному місці. Коли вітрин вісім, у кожної зʼявляється власна думка про те, скільки коштує товар і чи є він узагалі.

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

Рішення нудне й правильне: одне джерело правди на ціну, одне на залишок і автоматика, яка регулярно зводить решту до них. Уся складність - у деталях цього «зводить».

8
вітрин з одного джерела цін
10 хв
періодичність оновлення залишків
3 710
карток товару створено автоматично

Проблема: у кожної вітрини своя думка про ціну

Здається, що ціна - це просто число, яке треба скопіювати в кілька місць. Насправді кожен майданчик зберігає її по-своєму, і копіювати доводиться не число, а рішення.

Ручна робота тут росте не разом з каталогом, а разом з добутком: кожна зміна ціни множиться на кількість вітрин. Один товар подорожчав - вісім місць треба відкрити, знайти й виправити.

Три причини, чому ціни розʼїжджаються самі собою

🏷️ Різна механіка знижок

  • Десь базова ціна й акція - два різні поля, десь одне спільне
  • Той самий товар може стояти за акційною ціною на одному майданчику й за повною на іншому
  • Менеджер називає клієнту ту ціну, яку бачить у себе, а не ту, яку бачить клієнт

🔤 Артикули не збігаються

  • На складі товар живе під коротким кодом
  • На вітринах - під довгими ідентифікаторами, різними на кожному майданчику
  • У CRM лишився той код, що прийшов першим

⚠️ Ручна робота масштабується лінійно

  • Одна зміна ціни - вісім окремих дій
  • Пропустити одне місце легко, помітити пропуск важко
  • Помиляється не людина, помиляється сама схема роботи

Оновлення цін колись було одним рядком серед інших дрібних автоматизацій. Саме з нього і виріс окремий контур: ручна робота росла швидше за каталог.

Як автоматизація це вирішує

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

Потоки навмисно розділені: ціна змінюється рідко й обдумано, залишок - постійно й механічно. Змішувати їх в один прогін означає або гальмувати залишки, або смикати ціни занадто часто.

Два незалежні потоки: ціни і залишки
Майстер цін ефективна ціна зі знижкою різниця з поточною 8 вітрин
Складська програма розгортання артикулів дедуплікація CRM і майданчики

Ефективна ціна, а не базова

Система рахує не ту ціну, що записана в довіднику, а ту, яку клієнт реально бачить у магазині: базову, а якщо на товарі активна знижка - знижену.

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

Пишемо тільки різницю

Перед записом система порівнює нову ціну з тією, що стоїть на вітрині зараз. Якщо вони однакові, запису не відбувається взагалі.

Тому прогін, у якому нічого не змінилось, не залишає в магазині жодного сліду. Це і дешевше за лімітами чужих API, і чесніше: у журналі змін видно тільки справжні зміни.

Що це дало бізнесу

У компанії зʼявилась одна відповідь на питання «скільки це коштує». Ціна на всіх вітринах походить з одного місця, залишок - зі складу, і людина більше не переносить числа руками.

Окремим результатом стала разова частина. Перед запуском виявилось, що складська програма веде приблизно третину карток, а решта товарів заводилась повз неї - тобто половина каталогу для системи обліку просто не існувала.

Каталог CRM до і після разової міграції
Було позицій у каталозі6 739
Стало після автоматичного створення карток10 449

Створено 3 710 карток, залишки залито на 3 628 з них, а 3 314 позицій уперше в житті стали «в наявності».

Чесно про межі. Система свідомо вміє передавати менше, ніж могла б: якщо службова таблиця відповідностей застаріла, вона не розкладає залишки за здогадом, а віддає дані так, як отримала.

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

Як це влаштовано всередині

Далі - інженерна частина

Наступний розділ пояснює, як система влаштована. Якщо вас цікавить лише результат, його можна пропустити - нижче є розділ про те, кому це підходить.

Розгортання артикулів

Складська програма знає товар під коротким кодом і шле залишки саме так: близько 1 150 позицій кожні десять хвилин. На вітринах той самий товар живе під довгими ідентифікаторами, різними на кожному майданчику.

Тому приймач розгортає кожен короткий код на всі відомі артикули майданчиків за таблицею з 9 451 пари і передає далі вже один пакет на 3 650 позицій. Сама таблиця відповідностей будується автоматично щоночі з вивантажень вітрин - її ніхто не веде руками.

Що робить система, коли не впевнена

Якщо таблиця відповідностей не оновлювалась довше двох діб, розгортання вимикається і пакет іде наскрізь так, як прийшов. Факт роботи в такому режимі пишеться в журнал, тому деградація не буває тихою.

Друге правило стосується відмов на чужому боці. Якщо CRM не відповідає, приймач повертає складській програмі код помилки, а не код успіху, щоб та повторила пакет наступним циклом. Це вже перевірено на живому інциденті: перший бойовий пакет упав, повтор приїхав сам.

Клас помилок, який трапився двічі

Автоматичне заведення товарів ламалось двічі, і обидва рази причина була одна - загублене поле у вивантаженні.

Перший раз не копіювалась категорія. Автостворення тихо не створювало нічого: кандидатів нуль, при тому що лічильник відсіву «без категорії» був ненульовий. Нічого не падало, у журналах не було жодної помилки.

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

Симптом сформульований на майбутнє так: нуль кандидатів при ненульовому лічильнику відсіву - це майже завжди втрачене поле, а не порожні дані. Тепер це перше, що перевіряється, коли автоматика працює без помилок і без результату.

Три пастки чужих платформ, на які варто розраховувати заздалегідь
Втрачене полеДані доходять, але не всі. Фільтр на наступному кроці відсіює все, і зовні це виглядає як «просто нема чого створювати». Лічильники відсіву мають бути окремими, інакше різницю не видно
Мовчазний пропускПлатформа пропускає товар, назва якого вже зайнята, і при цьому рапортує успіх. «Створено 200» може насправді означати «створено 40», тому результат перевіряється не за відповіддю, а за станом каталогу
Сумування кількостейКількості кількох пропозицій підсумовуються в картку товару. Причепити ще один артикул до наявної картки означає завищити залишок, тому картки створюються, а не доповнюються

Кому це підходить

Усім, хто продає той самий товар більш ніж на двох майданчиках: власним сайтам разом з маркетплейсами, роздрібу з мобільним застосунком, гуртовикам із власним складом і кабінетом для клієнтів.

Побутова ознака, за якою легко перевірити, чи це про вас: якщо після зміни ціни хтось у компанії відкриває список місць, де її треба поправити, - так, це про вас. А якщо такого списку немає, то десь ціна вже стара, і ви про це ще не знаєте.

Синхронізація каталогу - це не про API. Це про те, щоб у компанії була одна відповідь на питання «скільки це коштує».

Потрібне схоже рішення?

Опишіть задачу - підберу архітектуру під ваш бюджет і дані.