POST /api/catalog/products/{id}/recalc-retail (Admin/Manager/Storekeeper):
- Если у Group товара задан MarkupPercent — записывает в дефолтный
розничный PriceType значение ceil(Cost * (1 + pct/100)). Округление
под AllowFractionalPrices: до сотых при включённом, до целого иначе.
- Возвращает 400 «У группы не задана наценка. …» если MarkupPercent null.
- Возвращает 400 если нет ни одного активного PriceType.
- Использует Organization.DefaultCurrencyId как fallback при создании
новой записи цены.
Background/ReferencePriceRefreshJob (IHostedService, PeriodicTimer 24ч):
- Раз в сутки находит товары с LastSupplyAt < now-30d и Cost > 0,
переписывает ReferencePrice = Cost, обновляет ReferencePriceUpdatedAt.
- IgnoreQueryFilters — работает над всеми organizations.
- Стартовая задержка 5 минут чтобы не пересечься с пендинг-миграцией.
- Зарегистрирован через AddHostedService в Program.cs.
- Hangfire не подключаем как полноценный server — IHostedService даёт
тот же эффект без отдельной schema/dashboard.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>