# Bug #004 — Очень малая цена (0.0000001) тихо округляется в 0 **Severity:** Low (бизнес-логика, не security) **Component:** `ProductsController.Create/Update/UpdatePrice/BulkUpdate.price-adjust` **Found:** Sprint 23, 2026-06-08 ## Воспроизведение ```bash POST /api/catalog/products { ..., "prices": [{"priceTypeId":"…", "amount": 0.0000001, "currencyId": "…"}] } ``` Ответ: **201 Created**. Перечитываем — `price.amount = 0.0`. Контроллер делает `RoundIfNeeded(0.0000001, allowFractional=true)` = `Math.Round(0.0000001, 2)` = `0.00`. БД-колонка `decimal(18,4)` сохраняет `0`. В `FindMissingRequiredPriceAsync` проверка `price.Amount <= 0m` происходит ДО округления — `0.0000001 > 0`, проходит. После округления — 0, но required-price-check уже не повторяется. ## Ожидание Один из вариантов: 1. Validator отвергает: «цена меньше 0.01 — введите как минимум 0.01». 2. Округлять ДО проверки required. 3. Документировать: «цены округляются до настроек организации; 0.0000001 → 0». ## Фикс Выбираем (2) — повторно проверить после `RoundIfNeeded`, чтобы required price check учитывал то что реально окажется в БД. ```csharp foreach (var pr in input.Prices ?? []) { var rounded = RoundIfNeeded(pr.Amount, allowFractional); if (rounded < 0m) return BadRequest(...); // Если PriceType.IsRequired — округлённое значение должно быть > 0. } // Перевалидируем required AFTER rounding: if (await FindMissingRequiredPriceAsync(/* rounded */, ct) is { } missing) return BadRequest(...); ``` Проще: добавить в `FindMissingRequiredPriceAsync` округление перед сравнением (или дополнить проверку в начале `Create`/`Update` после Apply). ## Severity rationale Бизнес-проблема (товар с нулевой ценой не попадёт на чек правильно — а "required" type'ы существуют именно чтобы гарантировать НЕ-нулевую цену), но эксплоит ограничен авторизованным admin'ом. Не критично, но фиксим.