SeRental
Прокат техніки на мультитенантній CMS
SeRental — прокат знімальної техніки: камери, оптика, світло, стабілізація, від однієї доби. Вітрина — сайт на Next.js без власної бази: кожен товар, ціна, категорія і спосіб оплати приходять із Nexus, мультитенантної CMS нашої розробки, через публічний API з авторизацією по ключу. Оренда — одна з семи вертикалей, які обслуговує та сама платформа.
Виклик
Прокат — це не магазин. Той самий об'єктив вільний наступного тижня і зайнятий завтра, ціна залежить від того, наскільки довго ви його тримаєте, а два клієнти можуть забронювати ту саму одиницю в ту саму секунду. Плюс власник хотів знижки за тривалість без переписування драбини на 138 позицій і передоплату карткою, яка сама повертається, якщо бронювання не підтвердили.
Що ми зробили
Наявність вирішується в кошику, проти реальних бронювань, а календар гасить дати, на які комплект не стане. Знижки — одна спільна сітка відсотків, адресована на все, на категорію або на окрему позицію, і перемагає найвужчий адресат. Подвійне бронювання відмовляє сама база — exclusion constraint Postgres по діапазонах часу, а не код, який може програти гонку. Оплата карткою несе адресу колбеку в кожному рахунку, а скасування оплаченого бронювання повертає гроші тією ж дією.
Результат
Жива вітрина на платформі, якою власник керує сам: ціни, тарифи, категорії, послуги і способи оплати редагуються в адмінці й з'являються на сайті без деплою. Оплата, повернення і наявність тримаються на сервері, тож те, що бачить клієнт, і те, що з нього беруть, не може розійтися.
Що вміє продукт
Кожен екран нижче — живий продукт, знятий цього тижня.
Вітрина
Прокат обирають за тим, що в ньому є і як швидко знаходиться потрібне, тому вхід — це пошук і категорія, а не буклет.
- 138 одиниць у 13 категоріях, пораховані з живого каталогу
- Пошук за назвою, категорії — прямо з адмінки
- Кожна цифра на сторінці виведена, жодної зашитої
Каталог і фасети
Фільтри будуються з характеристик, які завів оператор — байонет, формат матриці, тип оптики — і кожен лічильник рахується з усіма іншими фільтрами, але без себе самого.
- Лічильник не звужує власну групу, тож перемикання ніколи не показане нулем
- Ціна, наявність і характеристики — один спільний шар запитів
- Один запит сторінки плюс один прохід на всі незаймані осі, хоч який розмір каталогу
Тарифи
Ставка за добу падає з тривалістю оренди. Драбина написана один раз у відсотках і цінує весь магазин — від тримача за 100 ₴ до камери за 4 500 ₴.
- Одна сітка, адресована на все, на категорію або на окрему позицію
- Перемагає найвужчий адресат; одна активна сітка на адресата — тримає індекс
- Смуги не можуть перетинатися — відмовляє range exclusion constraint
Бронювання й оплата
Один період на весь комплект. Наявність перевіряється проти реальних бронювань, знижка названа в гривнях до того, як людина щось підтвердила, а картковий шлях закінчується бронюванням, яке оператор повертає однією дією.
- Календар гасить дати, на які позиція комплекту вже зайнята
- Повна сума, знижка й підсумок названі окремо, а не згорнуті в одне число
- Картка або готівка; непідтверджене бронювання повертає гроші саме
Кошик — місце, де сходяться дати, наявність і ціна. Зроблений спершу під телефон, зі знижкою, названою в гривнях.
Під капотом
Стек і інженерні рішення, на яких це зроблено.
- Одна драбина знижок на весь каталог — відсотки, а не таблиця, переписана в кожну позицію.
- Перетин бронювань відмовляє exclusion constraint у Postgres, тож два одночасні оформлення не можуть виграти обидва.
- Кошик питає в API сьогоднішні ціни, а не вірить тому, що зберіг при додаванні позиції.
- Скасування оплаченого бронювання робить повернення тією ж дією; шлюз, який відмовив, каже про це, а не звітує про успіх.
Маєте схожий проект?
Давайте поговоримо про те, як ми можемо створити щось чудове для вашого бізнесу. Ми любимо виклики.
Почати розмову