Skip to content

feat: Коммерческий аукцион (#179) + бейджи пользователей#199

Merged
ShaerWare merged 7 commits into
developfrom
feat/commercial-auction
Jul 13, 2026
Merged

feat: Коммерческий аукцион (#179) + бейджи пользователей#199
ShaerWare merged 7 commits into
developfrom
feat/commercial-auction

Conversation

@ShaerWare

Copy link
Copy Markdown
Owner

Summary

Ветка объединяет две линии работы (готовились слайсами и вошли в общие коммиты):

Коммерческий аукцион (#179), слайсы 1–6:

  • Модель данных этапа 2, движок скоринга и диапазонов, UI создания, price-only этап 1
  • Авто-запуск этапа 2, real-time предложения + UI, финальный PDF-протокол

Бейджи (ачивки) пользователей:

  • Админ выдаёт пользователям цветную рамку + подпись (пресеты красный/бордовый/зелёный + палитра; подписи «Подозрительная личность»/без подписи/«Подтверждён» + кастом). Несколько бейджей на юзера.
  • Новая таблица user_badges, модель UserBadge, связь User::badges().
  • Orchid: выдача на экране редактирования пользователя и массово из списка (addBadge/removeBadge/assignBadge).
  • Отображение: профиль, страницы и карточки RFQ/аукциона, ставки — только в раскрытых ветках (анонимность «Участник N» сохранена).

Docs: обновлён CHANGELOG_CLAUDE.md, добавлена строка про UserBadge в CLAUDE.md.

Relates to #179

Test plan

  • CI зелёный (Tests / Pint / Assets freshness)
  • test.bizzio.ru: коммерческий аукцион проходит полный цикл (создание → этап 1 → этап 2 → протокол)
  • Админка: выдать бейдж пользователю (пресет и палитра/кастом), удалить; массовая выдача из списка
  • Бейдж виден на профиле, на созданных пользователем RFQ/аукционе и в раскрытых результатах ставок; во время активной фазы на ставках бейдж скрыт

🤖 Generated with Claude Code

ShaerWare and others added 7 commits July 9, 2026 16:51
Аддитивные миграции и поля моделей для двухэтапной процедуры
«Коммерческий аукцион». Стандартные RFQ/аукционы не затрагиваются
(procedure='standard' по умолчанию, все новые колонки nullable).

- rfqs: procedure, trading_start/end, step_*, max_deadline/advance,
  linked_auction_id.
- auctions: procedure, rfq_id, weight_*, step_*, max_*, best_bid_id.
- auction_bids: deadline, advance_percent, score_*, total_score,
  is_base, became_best_at; type расширен значением 'offer'
  (pgsql — пересоздание CHECK, sqlite — перестройка колонки).
- Модели: isCommercial(), linkedAuction()/rfq()/bestBid()/offerBids()/
  baseBids()/bestOfferHistory(), isOffer(), fillable/casts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CommercialAuctionScoringService — фиксированная линейная нормировка от
максимумов-референсов (единая для цены/срока/аванса, 0..100), взвешенный
итог, проверка «строго лучше» (непрерывное лидерство), пер-критерий анализ
с зелёной «Лучший критерий» и замкнутым порогом «Уменьшите до X».

9 юнит-тестов (без БД): нормировка, ручной расчёт баллов, wouldBeat,
инверсия порога (подстановка даёт цель), зелёная метка, дефицит.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ce 3)

- StoreRfqRequest: procedure + поля этапа 2 (trading_start/end, step_*,
  max_deadline/advance) обязательны при procedure=commercial.
- RfqController::store: сохраняет параметры этапа 2; storeBid на этапе 1
  коммерческого RFQ валидирует и хранит только цену (срок/аванс = null).
- Миграция: rfq_bids.deadline/advance_percent → nullable.
- rfqs/create: переключатель «Запрос цен / Коммерческий аукцион» +
  секция параметров этапа 2 (Alpine x-show).
- rfqs/show: форма заявки этапа 1 скрывает срок/аванс для commercial.
- 4 feature-теста (создание, обязательность полей, standard без этапа 2,
  заявка «только цена»).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CommercialAuctionLauncherService: по закрытию этапа 1 создаёт связанный
  аукцион (НМЦ = макс. цена этапа 1, перенос весов/шагов/референсов,
  приглашает всех участников, статус trading). Идемпотентно; без
  участников — процедура несостоялась.
- CloseRfqJob: для commercial пропускает скоринг/победителя/протокол,
  вызывает launcher и закрывает этап 1.
- AuctionWinnerService::determineWinner: для commercial победитель = лучшее
  предложение (best_bid_id).
- UpdateAuctionStatuses: commercial стартует сразу в trading (исключён из
  active→trading и idle-правил); закрывается по trading_end.
- 4 feature-теста.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- StoreCommercialOfferRequest + AuctionController::storeOffer: подача
  предложения (3 критерия) с lockForUpdate, проверкой строгого
  превосходства, is_base, обновлением best_bid_id/last_bid_at. Отклонение
  с дефицитом баллов; проверки участника/верификации/пределов.
- getState: расширенное состояние commercial (веса, референсы, шаги,
  лучшее предложение, история, время до окончания).
- Route auctions.offers.store.
- Партиал commercial-trading: «Настройка предложения» (ввод+слайдер+
  диапазон+подсказки на 3 критерия, зеркало скоринга в Alpine, long-poll
  5с, гейтинг кнопки), карточка лучшего предложения, история.
- 7 feature-тестов (приём/отклонение/смена лидера/участник/пределы/
  рендер/getState).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- CommercialAuctionProtocolService + pdfs/commercial-auction-protocol:
  организатор, победитель (наименование+ИНН), итоговые цена/срок/аванс,
  рейтинг, история лучших предложений (код+ИНН+значения+время).
- CloseAuctionJob: для commercial использует коммерческий шаблон протокола
  (в ту же коллекцию 'protocol' — переиспользуется скачивание/гейтинг).
- Feature-тест генерации протокола при закрытии.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Записан отчёт по бейджам (ачивкам) в CHANGELOG_CLAUDE.md, добавлена
строка про модель UserBadge в CLAUDE.md (реализация вошла в 73d58a2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ShaerWare
ShaerWare merged commit 0c46613 into develop Jul 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant