global-favorite-service

GlobalFavoriteService

Спільний модуль family-application-api для глобальних фаворитів RU.

Задача

  1. Збирати всі FamilyFavorite одного RU у FamilyGlobalFavorite.
  2. Віддавати нашому frontend один список Global Favorites для всіх Family.
  3. Віддавати TU, на яких вибраний RU є фаворитом.
  4. Зберігати цільовий для Electron прапорець senderIgnore.
  5. Віддавати Global Favorites і короткі профілі RU у стартових даних Electron.

Агрегація

Після FamilyFavoriteChanged сервіс читає зв’язки RU прямо з collection і перераховує один FamilyGlobalFavorite. Через RMQ передаються тільки family і ruExternalId, а не список favorites.

ПолеРозрахунок
firstPaidAtмінімальний firstPaidAt
lastPaidAtмаксимальний lastPaidAt
tuCountкількість зв’язків TU + RU
contactsкількість зв’язків із contacts.status = Yes
profitсума profit
paidProfitсума paidProfit
giftsсума gifts
isFreeloaderpaidProfit не досяг Family-порогу

Перерахунок є idempotent: агрегат щоразу будується з поточних FamilyFavorite, а senderIgnore і профіль RU не перезаписуються.

Freeloader

paidProfit — цільова нормалізація, а не поле поточних моделей. Вона потрібна, щоб новий сервіс рахував один isFreeloader, не переносячи isFreeProfit і різні перевірки по коду.

FamilyПоточна реалізаціяЦільовий розрахунок
GoldenРозрахунок Freeloader не реалізованийреальні витрати paidProfit > 0
PrimeGlobalMan.profit < 11платні повідомлення paidProfit >= 11
ChathouseGlobalMan.isFreeProfit: усі credits були freeвитрати без free credits paidProfit > 0
UdateGlobalMan.profit < 11платні повідомлення paidProfit >= 11

У Udate глобальна перевірка вважає RU платним при 11, але одна socket-task перевіряє > 11. У новій реалізації має залишитися одна перевірка >= 11.

Frontend API

ОпераціяEndpoint
1Список Global FavoritesGET /families/{family}/global-favorites
2TU вибраного RUGET /families/{family}/global-favorites/{ruExternalId}/favorites
3Увімкнути або вимкнути цільове поле senderIgnorePATCH /families/{family}/global-favorites/{ruExternalId}

Список підтримує pagination, пошук за externalId або ім’ям і сортування за датами, online, кількістю TU, contacts, gifts та profit. Другий endpoint може фільтрувати зв’язки за contacts або gifts.

Director бачить усі RU Family. Supervisor і Top Manager бачать RU, пов’язаних хоча б з однією доступною їм TU; у вкладеному списку повертаються лише доступні TU. Сам агрегат RU завжди рахується по всій Family.

Нотатка, яку зараз редагують на сторінці Global Favorites, буде читатися й змінюватися через NotesService.

Внутрішні операції

ОпераціяХто використовує
1Перерахувати Global Favorite за family + ruExternalIdFamilyFavoriteService
2Отримати Global Favorites за списком доступних TUElectron StartupDataService

Окремий worker не потрібен: звичайне оновлення запускається разом зі зміною FamilyFavorite. Для первинної міграції або ремонту даних потрібен idempotent rebuild усієї проєкції.

Межі

  • Короткий профіль RU оновлюється з уже отриманих partner-відповідей та Electron data sync.
  • lastOnlineAt оновлює логіка RU online.
  • Поточний Prime Agency blacklist переноситься у senderIgnore; frontend та Electron SenderService змінюють одне поле.
  • GlobalFavoriteService не виконує partner-запитів і не містить Family-adapterів.

Agency

  • Prime Agency blacklist — це ручне виключення RU із сендерів, тому окремий AgencyService для нього не потрібен.
  • AgencyService — окрема Family-wide логіка актуальних, нових і втрачених платних RU для Golden і Chathouse. Це не календар New / Unique RU конкретної TU у FavoriteService.