# Корзины по складам для оптовых покупателей

> Корзина для оптовых витрин inSales, где покупатель выбирает количество отдельно для каждого склада. Общая библиотека витрин отправляет изменения по нескольким складам одним запросом. В production — к ноябрю 2023 года.

- Адрес: https://anu3ev.com/ru/work/multi-warehouse-carts/
- Период: Август – ноябрь 2023
- Где: inSales
- Роль: Отвечал за реализацию на витрине и согласование API
- Навыки: JavaScript, API Development, AJAX, State Management, E-Commerce, Debugging, Front-End Development, API Integration, Requirements Analysis

## Задача

Некоторые магазины на inSales продают оптом сразу из нескольких источников: со своего склада и со склада партнёра, в одном каталоге. Оптовику нужно заказать один и тот же товар так: 15 штук с основного склада и 8 с партнёрского. Корзина должна держать эти выборы раздельно, у каждого склада свои количества и своя сумма.

Корзина витрины была рассчитана на один список товаров. Все операции с ней в CommonJS, общей JavaScript-библиотеке витрин inSales, исходили из того, что корзина одна. Вызывают библиотеку отовсюду: из карточки товара, каталога, главной, блоков сопутствующих товаров. Любая правка в ней затрагивает множество магазинов, в том числе тех, у кого один склад и кому эта функция не нужна.

## Моя роль

Проект был на мне от реализации на витрине до production. Я дорабатывал общую библиотеку, формулировал нужные фронтенду изменения API и согласовывал формат ответа с backend-разработчиком, который делал серверную часть. С продуктовым менеджером уточнял приоритеты и открытые продуктовые вопросы, при тестировании разбирал сбои в корзинах по складам. Начал в августе 2023 года, к ноябрю функция уже работала в production.

## Что я сделал

### Склад передаётся в каждой операции с корзиной

В операциях добавления, изменения и удаления товара нельзя было указать, к какому складу относится изменение. Я добавил выбранный склад во все три, и карточка товара с двумя полями количества стала обновлять группу нужного склада. Заодно договорился с бэкендом, на какие поля ответа опирается интерфейс. Например, склад на верхнем уровне ответа означает склад основной корзины, и это не обязательно склад последней операции. Под эти договорённости я и переделал обработку ответа в библиотеке.

### Расчёт количества начинается с выбранного склада

Когда покупатель вводит новое количество, библиотека считает, сколько штук добавить или убрать. Исходное значение она брала не из той корзины, и изменение для одного склада могло считаться от количества на другом. Я исправил расчёт: текущее количество берётся из группы выбранного склада. Если там 15 штук, а покупатель просит 5, библиотека убирает 10.

Доступный остаток и заказанное количество тоже разные данные. Я запросил у бэкенда остаток по каждому товару внутри группы склада: прежнее поле количества говорило только о том, сколько заказал покупатель.

### Пересекающиеся запросы теряли выбор

На тестировании я заметил, что быстрые изменения по разным складам могут перезаписывать друг друга. Покупатель выбирал товары на обоих складах, а в корзине оставался выбор только по одному. Библиотека и раньше объединяла накопленные задачи в один запрос, но старый API принимал один склад на запрос. Изменения по двум складам уходили отдельно и могли пересечься.

Я описал сбой и сформулировал требование: библиотека собирает изменения по нескольким складам и отправляет их группами в одном запросе, а сервер раскладывает каждую группу в корзину своего склада. Серверную часть сделал backend-разработчик.

### Обычная корзина работает как раньше

Запрос без склада выключал режим корзин по складам, а одновременно два режима работать не могли. Один и тот же товар можно добавить из разных виджетов на странице, поэтому я проверял, сохраняется ли выбор складов при добавлении из каталога, с главной и из сопутствующих товаров. Данные обычной корзины обрабатывал отдельно от сгруппированных по складам. Магазины с одним складом сохранили привычные поля количества и свой код.

### Карточка товара и корзина показывают одни и те же числа

Я связал обновления корзин по складам с полями количества в карточке товара: и там, и в корзине видно, сколько выбрано на каждом складе. Ещё разбирал случай, когда покупатель меняет количество и сразу переходит к оформлению. На сервер уходили два запроса, последний ответ был верным, а виджет показывал результат первого. Я воспроизвёл сценарий и записал его для команды.

## Результат

- К ноябрю 2023 года функция работала в production. Работу я начал в августе 2023-го.
- Оптовый покупатель выбирает количество отдельно для каждого склада, а корзина показывает по каждому складу свои количества и сумму.
- Групповое обновление вышло в production: изменения по нескольким складам уходят на сервер одним запросом. Так закрылся найденный мной на тестировании случай с потерей выбора.
- Магазины с одним складом остались на обычной корзине, их код менять не пришлось.

Своих цифр по использованию или выручке от этой функции у меня нет. Зачем вообще продавать партнёрские остатки, видно по [кейсу, который опубликовал inSales](https://www.insales.ru/blogs/cases/hited): у одного магазина с каталогом на 45 000 SKU партнёрские склады дали 21% онлайн-продаж за 2024 год. Это показатель самого магазина, а не результат моей работы.
