GlobalFavoriteService
Спільний модуль family-application-api для глобальних фаворитів RU.
Задача
- Збирати всі FamilyFavorite одного RU у FamilyGlobalFavorite.
- Віддавати нашому frontend один список Global Favorites для всіх Family.
- Віддавати TU, на яких вибраний RU є фаворитом.
- Зберігати цільовий для Electron прапорець
senderIgnore. - Віддавати 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 |
isFreeloader | paidProfit не досяг Family-порогу |
Перерахунок є idempotent: агрегат щоразу будується з поточних FamilyFavorite, а senderIgnore і профіль RU не перезаписуються.
Freeloader
paidProfit — цільова нормалізація, а не поле поточних моделей. Вона потрібна, щоб новий сервіс рахував один isFreeloader, не переносячи isFreeProfit і різні перевірки по коду.
| Family | Поточна реалізація | Цільовий розрахунок |
|---|---|---|
| Golden | Розрахунок Freeloader не реалізований | реальні витрати paidProfit > 0 |
| Prime | GlobalMan.profit < 11 | платні повідомлення paidProfit >= 11 |
| Chathouse | GlobalMan.isFreeProfit: усі credits були free | витрати без free credits paidProfit > 0 |
| Udate | GlobalMan.profit < 11 | платні повідомлення paidProfit >= 11 |
У Udate глобальна перевірка вважає RU платним при 11, але одна socket-task перевіряє > 11. У новій реалізації має залишитися одна перевірка >= 11.
Frontend API
| № | Операція | Endpoint |
|---|---|---|
| 1 | Список Global Favorites | GET /families/{family}/global-favorites |
| 2 | TU вибраного RU | GET /families/{family}/global-favorites/{ruExternalId}/favorites |
| 3 | Увімкнути або вимкнути цільове поле senderIgnore | PATCH /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 + ruExternalId | FamilyFavoriteService |
| 2 | Отримати Global Favorites за списком доступних TU | Electron 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.