# ReviewsService ## Назначение Сервис управляет пользовательским контентом по товарам: отзывами и вопросами. Поддерживает публикацию сообщений (текст + фото), модерацию, ответы на вопросы, а также систему лайков/дизлайков. Дополнительно формирует агрегированную аналитику по товарам (средняя оценка, количество отзывов, лучшие отзывы, последние 10 и список вопросов). Контроль доступа осуществляется через NBSession. Публикуются контент только прошедший модерацию. Далее отзыв и вопрос, если не имеет принципиальной разницы называется сообщением. Для администрирования необходимо иметь доступ [AccessTypeEnum](/common/accessTypeEnum.md).ReviewsQuestionsControl. ## Публичные методы * `GetMyReviewsAndQuestionsAsync(skip = 0, take = 50): ProductMessage[]` - вернуть список сообщений, созданных текущим пользователем (отзывы и вопросы). * `GetReviewsReportAsync(productId): ProductReviewsReport` - агрегированный отчёт по отзывам для товара. * `GetQuestionsReportAsync(productId): ProductQuestionsReport` - агрегированный отчёт по вопросам для товара. * `GetRatesAsync(productIds[]): float[]` - массив средних оценок для списка товаров. * `GetReviewsAsync(productId, skip = 0, take = 10): ProductMessage[]` - список отзывов по товару с постраничной выборкой. * `GetReviewsToApprove(skip = 0, take = 10): ProductMessage[]` - список отзывов, ожидающих модерации. * `GetQuestionsToApprove(skip = 0, take = 10): ProductMessage[]` - список вопросов, ожидающих модерации. * `GetMessageAsync(id): ProductMessageFull` - сообщение по идентификатору. * `ApproveProductMessageAsync(messageId, answerText): void` - подтвердить сообщение (модерация) и при необходимости добавить текст ответа. * `DeleteProductMessageAsync(messageId): void` - удалить сообщение (отзыв или вопрос). * `PostReviewAsync(review): ProductMessage` - опубликовать новый отзыв. * `PostQuestionAsync(question): ProductMessage` - опубликовать новый вопрос. * `ReactOnMessageAsync(messageId, isLike): ProductMessage` - поставить реакцию (лайк или дизлайк) на сообщение и вернуть обновлённое. ## Особенности и правила * **Типы сообщений**: `ProductMessage.Type` определяет отзыв или вопрос; у отзывов может быть `Rate`, у вопросов - `Rate=0`. * **Связи**: поле `ReplyToId` позволяет строить дерево (вопрос → ответ), массив `RepliesIds` хранит идентификаторы ответов. * **Модерация**: поле `IsApproved` устанавливается администратором. Только подтверждённые сообщения видны обычным пользователям. * **Агрегированные отчёты**: * Отзывы: средняя оценка (`RateMiddle`), количество (`ReviewsCount`), все фото (`ReviewsAllFotos`), лучший отзыв (`BestReview`), последние 10 (`ReviewsLast10`). * Вопросы: количество (`QuestionsCount`), список всех вопросов с ответами (`QuestionsAll`). * **Лайки и дизлайки**: модель `LikesRecord` фиксирует реакцию пользователя (`TargetId`, `UserId`, `Value`). Один пользователь может иметь только одну реакцию на сообщение. * **Контроль доступа**: пользователь может удалять/редактировать только свои сообщения; модераторы - любые. NBSession гарантирует проверку авторства и прав. ## Взаимодействие c другими сервисами ``` / [ProfilesService] [ReviewsService] <-----[DirectoryService] \ [FilesDirectoryService] ``` ReviewsService запрашивает данные (get only) у следующих сервисов: * ProfileService - запрос имени пользователя, если тот не указал иное при создании контента. * DirectoryService - запрос на проверку существования и наименования товара, по которому создается контент. * FileDirectoryService - проверка на наличие указанных файлов (прикрипленных фото). ## Модели ### ProductMessage ``` ProductMessageTypeEnum Type – тип сообщения (отзыв или вопрос) long Id – идентификатор сообщения long ReplyToId – идентификатор сообщения, на которое дан ответ (0, если это не ответ) long[] RepliesIds – список идентификаторов ответов int ProductId – идентификатор товара string ProductName – название товара long OwnerId – идентификатор пользователя, оставившего сообщение string OwnerName – имя пользователя string Text – текст сообщения int Rate – оценка (1–5 для отзывов, 0 для вопросов) string[] Fotos – список ссылок на фотографии, прикреплённые к сообщению int LikesCount – количество лайков int DislikesCount – количество дизлайков DateTimeOffset Created – дата и время создания сообщения bool IsApproved – признак того, что сообщение прошло модерацию ``` ### ProductReviewsReport ``` int ProductId – идентификатор товара float RateMiddle – средняя оценка товара по отзывам int ReviewsCount – количество отзывов string[] ReviewsAllFotos – все фотографии из отзывов по товару ProductMessage? BestReview – лучший отзыв ProductMessage[] ReviewsLast10 – последние 10 отзывов ``` ### ProductQuestionsReport ``` int ProductId – идентификатор товара int QuestionsCount – количество вопросов по товару ProductMessage[] QuestionsAll – список всех вопросов с привязанными ответами ``` ### LikesRecord ``` long TargetId – идентификатор сообщения, к которому относится лайк/дизлайк int UserId – идентификатор пользователя, оставившего реакцию int Value – значение реакции (1 = лайк, -1 = дизлайк) ``` ### ProductMessageTypeEnum ``` Unknown = 0 – неопределённый тип сообщения Review = 1 – отзыв о товаре Question = 2 – вопрос о товаре ``` ## DB Содержит таблицы и индексы ``` -- Migration 1 messages ( Id INTEGER PRIMARY KEY, Type INTEGER NOT NULL, ReplyToId INTEGER NOT NULL, RepliesIds TEXT NOT NULL DEFAULT '[]', ProductId INTEGER NOT NULL, ProductName TEXT NOT NULL DEFAULT '', OwnerId INTEGER NOT NULL, OwnerName TEXT NOT NULL DEFAULT '', Text TEXT NOT NULL DEFAULT '', Rate INTEGER NOT NULL, Fotos TEXT NOT NULL DEFAULT '[]', LikesCount INTEGER NOT NULL, DislikesCount INTEGER NOT NULL, Created INTEGER NOT NULL, IsApproved BOOLEAN NOT NULL DEFAULT FALSE ); likes ( TargetId INTEGER NOT NULL, UserId INTEGER NOT NULL, Value INTEGER NOT NULL, PRIMARY KEY (TargetId, UserId) ) ``` [Назад](../../../index.md)