| | | 1 | | using OzonDomains.Models; |
| | | 2 | | using OzonRepositories.Data; |
| | | 3 | | |
| | | 4 | | namespace Services.DataServices |
| | | 5 | | { |
| | | 6 | | public class OzonChatResponseStatisticDataServices : IDataServices |
| | | 7 | | { |
| | | 8 | | private readonly OzonChatResponseStatisticRepository _repository; |
| | | 9 | | |
| | 0 | 10 | | public OzonChatResponseStatisticDataServices(OzonChatResponseStatisticRepository repository) |
| | | 11 | | { |
| | 0 | 12 | | _repository = repository; |
| | 0 | 13 | | } |
| | | 14 | | |
| | | 15 | | public async Task<int> Add(OzonChatResponseStatistic value) |
| | | 16 | | { |
| | 0 | 17 | | return await _repository.Add(value); |
| | 0 | 18 | | } |
| | | 19 | | |
| | | 20 | | public async Task<int> Delete(OzonChatResponseStatistic value) |
| | | 21 | | { |
| | 0 | 22 | | return await _repository.Delete(value); |
| | 0 | 23 | | } |
| | | 24 | | |
| | | 25 | | public async Task<List<OzonChatResponseStatistic>> Get() |
| | | 26 | | { |
| | 0 | 27 | | return await _repository.Get(); |
| | 0 | 28 | | } |
| | | 29 | | |
| | | 30 | | public async Task<OzonChatResponseStatistic?> GetAsync(int id) |
| | | 31 | | { |
| | 0 | 32 | | return await _repository.GetAsync(id); |
| | 0 | 33 | | } |
| | | 34 | | |
| | | 35 | | public async Task<OzonChatResponseStatistic?> GetAsync(OzonChatResponseStatistic value) |
| | | 36 | | { |
| | 0 | 37 | | return await _repository.GetAsync(value); |
| | 0 | 38 | | } |
| | | 39 | | |
| | | 40 | | public async Task<int> Update(OzonChatResponseStatistic value) |
| | | 41 | | { |
| | 0 | 42 | | return await _repository.Update(value); |
| | 0 | 43 | | } |
| | | 44 | | |
| | | 45 | | public async Task<int> SaveChanges() |
| | | 46 | | { |
| | 0 | 47 | | return await _repository.SaveChanges(); |
| | 0 | 48 | | } |
| | | 49 | | |
| | | 50 | | /// <summary> |
| | | 51 | | /// Получить статистику по чату |
| | | 52 | | /// </summary> |
| | | 53 | | public async Task<List<OzonChatResponseStatistic>> GetByChatIdAsync(string chatId) |
| | | 54 | | { |
| | 0 | 55 | | return await _repository.GetByChatIdAsync(chatId); |
| | 0 | 56 | | } |
| | | 57 | | |
| | | 58 | | /// <summary> |
| | | 59 | | /// Получить статистику по клиенту |
| | | 60 | | /// </summary> |
| | | 61 | | public async Task<List<OzonChatResponseStatistic>> GetByClientIdAsync(int clientId, DateTime? from = null, DateT |
| | | 62 | | { |
| | 0 | 63 | | return await _repository.GetByClientIdAsync(clientId, from, to); |
| | 0 | 64 | | } |
| | | 65 | | |
| | | 66 | | /// <summary> |
| | | 67 | | /// Получить неотвеченные сообщения по клиенту |
| | | 68 | | /// </summary> |
| | | 69 | | public async Task<List<OzonChatResponseStatistic>> GetUnansweredByClientIdAsync(int clientId) |
| | | 70 | | { |
| | 0 | 71 | | return await _repository.GetUnansweredByClientIdAsync(clientId); |
| | 0 | 72 | | } |
| | | 73 | | |
| | | 74 | | /// <summary> |
| | | 75 | | /// Получить статистику по заказу |
| | | 76 | | /// </summary> |
| | | 77 | | public async Task<List<OzonChatResponseStatistic>> GetByOrderIdAsync(int orderId) |
| | | 78 | | { |
| | 0 | 79 | | return await _repository.GetByOrderIdAsync(orderId); |
| | 0 | 80 | | } |
| | | 81 | | |
| | | 82 | | /// <summary> |
| | | 83 | | /// Получить запись по ID сообщения клиента |
| | | 84 | | /// </summary> |
| | | 85 | | public async Task<OzonChatResponseStatistic?> GetByClientMessageIdAsync(string chatId, long clientMessageId) |
| | | 86 | | { |
| | 0 | 87 | | return await _repository.GetByClientMessageIdAsync(chatId, clientMessageId); |
| | 0 | 88 | | } |
| | | 89 | | |
| | | 90 | | /// <summary> |
| | | 91 | | /// Создать или обновить запись статистики сообщения клиента |
| | | 92 | | /// </summary> |
| | | 93 | | public async Task<OzonChatResponseStatistic> CreateOrUpdateClientMessageAsync( |
| | | 94 | | string chatId, |
| | | 95 | | long clientMessageId, |
| | | 96 | | string clientMessageText, |
| | | 97 | | DateTime clientMessageDate, |
| | | 98 | | int clientId, |
| | | 99 | | int? orderId = null, |
| | | 100 | | string? postingNumber = null, |
| | | 101 | | string? chatType = null, |
| | | 102 | | string? chatStatus = null) |
| | | 103 | | { |
| | 0 | 104 | | var existing = await _repository.GetByClientMessageIdAsync(chatId, clientMessageId); |
| | | 105 | | |
| | 0 | 106 | | if (existing != null) |
| | | 107 | | { |
| | | 108 | | // Обновляем только если есть изменения |
| | 0 | 109 | | existing.ClientMessageText = clientMessageText; |
| | 0 | 110 | | existing.ClientMessageDate = clientMessageDate; |
| | 0 | 111 | | existing.OrderId = orderId ?? existing.OrderId; |
| | 0 | 112 | | existing.PostingNumber = postingNumber ?? existing.PostingNumber; |
| | 0 | 113 | | existing.ChatType = chatType ?? existing.ChatType; |
| | 0 | 114 | | existing.ChatStatus = chatStatus ?? existing.ChatStatus; |
| | 0 | 115 | | await _repository.Update(existing); |
| | 0 | 116 | | return existing; |
| | | 117 | | } |
| | | 118 | | |
| | | 119 | | // Создаем новую запись |
| | 0 | 120 | | var newStatistic = new OzonChatResponseStatistic |
| | 0 | 121 | | { |
| | 0 | 122 | | ChatId = chatId, |
| | 0 | 123 | | ClientId = clientId, |
| | 0 | 124 | | OrderId = orderId, |
| | 0 | 125 | | PostingNumber = postingNumber, |
| | 0 | 126 | | ClientMessageId = clientMessageId, |
| | 0 | 127 | | ClientMessageText = clientMessageText, |
| | 0 | 128 | | ClientMessageDate = clientMessageDate, |
| | 0 | 129 | | ChatType = chatType, |
| | 0 | 130 | | ChatStatus = chatStatus, |
| | 0 | 131 | | IsAnswered = false, |
| | 0 | 132 | | CreatedAt = DateTime.UtcNow, |
| | 0 | 133 | | UpdatedAt = DateTime.UtcNow |
| | 0 | 134 | | }; |
| | | 135 | | |
| | 0 | 136 | | await _repository.Add(newStatistic); |
| | 0 | 137 | | return newStatistic; |
| | 0 | 138 | | } |
| | | 139 | | |
| | | 140 | | /// <summary> |
| | | 141 | | /// Обновить информацию об ответе продавца |
| | | 142 | | /// </summary> |
| | | 143 | | public async Task<int> UpdateResponseAsync( |
| | | 144 | | string chatId, |
| | | 145 | | long clientMessageId, |
| | | 146 | | long sellerResponseMessageId, |
| | | 147 | | string sellerResponseText, |
| | | 148 | | DateTime sellerResponseDate, |
| | | 149 | | string? responderName = null) |
| | | 150 | | { |
| | 0 | 151 | | return await _repository.UpdateResponseAsync( |
| | 0 | 152 | | chatId, |
| | 0 | 153 | | clientMessageId, |
| | 0 | 154 | | sellerResponseMessageId, |
| | 0 | 155 | | sellerResponseText, |
| | 0 | 156 | | sellerResponseDate, |
| | 0 | 157 | | responderName); |
| | 0 | 158 | | } |
| | | 159 | | |
| | | 160 | | /// <summary> |
| | | 161 | | /// Получить среднее время ответа по клиенту за период |
| | | 162 | | /// </summary> |
| | | 163 | | public async Task<double?> GetAverageResponseTimeAsync(int clientId, DateTime? from = null, DateTime? to = null) |
| | | 164 | | { |
| | 0 | 165 | | return await _repository.GetAverageResponseTimeAsync(clientId, from, to); |
| | 0 | 166 | | } |
| | | 167 | | |
| | | 168 | | /// <summary> |
| | | 169 | | /// Получить статистику ответов (всего/отвечено) по клиенту за период |
| | | 170 | | /// </summary> |
| | | 171 | | public async Task<(int Total, int Answered, double AnswerRate)> GetAnswerStatsAsync( |
| | | 172 | | int clientId, DateTime? from = null, DateTime? to = null) |
| | | 173 | | { |
| | 0 | 174 | | return await _repository.GetAnswerStatsAsync(clientId, from, to); |
| | 0 | 175 | | } |
| | | 176 | | |
| | | 177 | | /// <summary> |
| | | 178 | | /// Получить топ-N самых медленных ответов по клиенту |
| | | 179 | | /// </summary> |
| | | 180 | | public async Task<List<OzonChatResponseStatistic>> GetSlowestResponsesAsync(int clientId, int topN = 10) |
| | | 181 | | { |
| | 0 | 182 | | return await _repository.GetSlowestResponsesAsync(clientId, topN); |
| | 0 | 183 | | } |
| | | 184 | | |
| | | 185 | | /// <summary> |
| | | 186 | | /// Получить статистику по типам чатов |
| | | 187 | | /// </summary> |
| | | 188 | | public async Task<Dictionary<string, int>> GetStatsByChatTypeAsync(int clientId, DateTime? from = null, DateTime |
| | | 189 | | { |
| | 0 | 190 | | return await _repository.GetStatsByChatTypeAsync(clientId, from, to); |
| | 0 | 191 | | } |
| | | 192 | | |
| | | 193 | | /// <summary> |
| | | 194 | | /// Добавить запись об ответе менеджера (упрощённый метод) |
| | | 195 | | /// </summary> |
| | | 196 | | public async Task<OzonChatResponseStatistic> AddManagerMessageAsync( |
| | | 197 | | string chatId, |
| | | 198 | | int clientId, |
| | | 199 | | string messageText, |
| | | 200 | | string responderName, |
| | | 201 | | long? sellerMessageId = null, |
| | | 202 | | int? orderId = null, |
| | | 203 | | string? postingNumber = null, |
| | | 204 | | string? chatType = null, |
| | | 205 | | string? chatStatus = null) |
| | | 206 | | { |
| | 0 | 207 | | var statistic = new OzonChatResponseStatistic |
| | 0 | 208 | | { |
| | 0 | 209 | | ChatId = chatId, |
| | 0 | 210 | | ClientId = clientId, |
| | 0 | 211 | | OrderId = orderId, |
| | 0 | 212 | | PostingNumber = postingNumber, |
| | 0 | 213 | | ClientMessageId = 0, // Не известно на какое сообщение отвечаем |
| | 0 | 214 | | ClientMessageText = null, |
| | 0 | 215 | | ClientMessageDate = DateTime.UtcNow, |
| | 0 | 216 | | SellerResponseMessageId = sellerMessageId, |
| | 0 | 217 | | SellerResponseText = messageText, |
| | 0 | 218 | | SellerResponseDate = DateTime.UtcNow, |
| | 0 | 219 | | ResponseTimeSeconds = 0, |
| | 0 | 220 | | IsAnswered = true, |
| | 0 | 221 | | ChatType = chatType ?? "BUYER_SELLER", |
| | 0 | 222 | | ChatStatus = chatStatus ?? "Opened", |
| | 0 | 223 | | ResponderName = responderName, |
| | 0 | 224 | | CreatedAt = DateTime.UtcNow, |
| | 0 | 225 | | UpdatedAt = DateTime.UtcNow |
| | 0 | 226 | | }; |
| | | 227 | | |
| | 0 | 228 | | await _repository.Add(statistic); |
| | 0 | 229 | | return statistic; |
| | 0 | 230 | | } |
| | | 231 | | |
| | | 232 | | /// <summary> |
| | | 233 | | /// Получить ChatId чатов, где сообщение покупателя содержит поисковый запрос |
| | | 234 | | /// </summary> |
| | | 235 | | public async Task<List<string>> GetChatIdsByMessageQueryAsync(string query, int clientId = 0, int limit = 100) |
| | | 236 | | { |
| | 0 | 237 | | return await _repository.GetChatIdsByMessageQueryAsync(query, clientId, limit); |
| | 0 | 238 | | } |
| | | 239 | | |
| | | 240 | | /// <summary> |
| | | 241 | | /// Получить образцы сообщений покупателей для построения списка подсказок |
| | | 242 | | /// </summary> |
| | | 243 | | public async Task<List<(string ChatId, string MessageText, string? PostingNumber, int ClientId)>> GetSampleBuyer |
| | | 244 | | string query, int clientId = 0, int limit = 200) |
| | | 245 | | { |
| | 0 | 246 | | return await _repository.GetSampleBuyerMessagesAsync(query, clientId, limit); |
| | 0 | 247 | | } |
| | | 248 | | } |
| | | 249 | | } |