Ілля Шкура
EN UK RU

Нотатки · жовтень 2026

Повернення, більше за замовлення: €500 записано за замовленням на €29,99.

Магазин трикотажу зібрали в Claude Code за 17 повідомленнями звичайними словами. Це демонстраційний магазин, зібраний для кейсу, з вигаданими покупцями й тестовими даними. У ньому є сторінка повернень: власник схвалює повернення, речі надходять назад, і власник повертає за них гроші. Оплати карткою повертаються на картку через Stripe. Якщо платили банківським переказом, власник надсилає гроші з банку й позначає повернення як виплачене, вписуючи суму, яку надіслав.

Цю суму перевіряли лише на одне: чи це число. Stripe не повернув би €500 на картку. Діра — у тому, що записав магазин: у замовленні, у звітах за місяць і в листі покупцеві.

Що сталося

Покупець повернув одну пару шкарпеток із замовлення на €29,99. Власник вписав 500 у поле суми й натиснув «Mark as refunded».

  • Суму прийнято. У замовленні значилося: повернуто €500.
  • Повернення за місяць на дашборді й у звітах зросли на €500.
  • Покупець отримав лист «Your refund of €500 is on its way».
  • Записане повернення потім не можна було виправити.
Сторінка повернень у зданому вигляді: повернення однієї речі за €24, а в панелі замовлення написано, що повернуто €500
У зданому вигляді: повернулася одна річ за €24, а записано повернення €500.

Вводити 500 навмисно нікому не треба. Те саме зробить одрук в одній цифрі або десяткова кома в полі, яке мовчки її відкидає: 23,99 від людини, звиклої до європейського запису чисел, перетворюється на 2399.

«Але ж Stripe не поверне більше, ніж заплатили»

Це правда, і саме тому цю діру легко проґавити. Stripe відмовляє в поверненні, більшому за те, що лишилося від платежу, тож сама картка в безпеці. Усе інше — ні:

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

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

Ще два шляхи до тієї самої діри

  • Два часткові повернення з одного замовлення. Дві речі з одного замовлення повернули окремо, двома поверненнями. Для кожного сторінка пропонувала ціну речі плюс вартість доставки. Погодьтеся з обома пропозиціями — і доставку повернуть двічі: за замовленням повернуто більше, ніж заплатив покупець, хоча ніде немає жодного одруку.
  • Два повернення в один момент. Та сама форма відкрита у двох вкладках, або поверненнями займаються двоє людей. Перевірка, яка живе лише на сторінці («чи це менше за залишок?»), пропускає обидва, бо кожне читає замовлення раніше, ніж інше встигає в нього записати.

Виправлення

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

Виправлена сторінка повернень: у полі суми введено 500, і суму відхилено з повідомленням, що це більше, ніж лишилося повернути за цим замовленням: €29,99
Після виправлення: 500 відхилено, а сторінка пише, скільки лишилося повернути.

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

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

Перевірте свій застосунок за п'ять хвилин

  • Знайдіть кожне місце, де записується повернення: сторінку в адмінці, кнопку «mark as refunded», обробник події Stripe charge.refunded, автоматизацію, яка записує повернення в таблицю.
  • Введіть суму, більшу за замовлення. Її відхиляють ще до збереження чи лише повідомленням на сторінці?
  • Зробіть за одним замовленням два часткові повернення, які разом перевищують сплачене.
  • Відкрийте форму повернення у двох вкладках і надішліть обидві одночасно.
  • Після кожної спроби подивіться на три речі: замовлення, суму повернень за місяць і лист, який отримав покупець.

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

Повний кейс зі знімками до і після та звітом на 22 сторінки: Інтернет-магазин, зібраний ШІ: перевірено й виправлено. Огляд усього, що знайшлося в цьому магазині: Магазин, що мав готовий вигляд.

Хочете перевірити ці випадки у своєму застосунку? Застосунки, зібрані з ШІ: кожна проблема — з кроками, що її показують, з тим, що вона робить із грошима, і з тестом виправлення.