OrderVisitDomainServiceTest.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. using Hotline.Api.Controllers;
  2. using Hotline.Application.Tests.Mock;
  3. using Hotline.Caching.Interfaces;
  4. using Hotline.EventBus;
  5. using Hotline.Identity.Accounts;
  6. using Hotline.Identity.Roles;
  7. using Hotline.Orders;
  8. using Hotline.Push.FWMessage;
  9. using Hotline.Push.Notifies;
  10. using Hotline.Settings;
  11. using Hotline.Share.Dtos;
  12. using Hotline.Share.Dtos.Push;
  13. using Hotline.Share.Enums.Order;
  14. using Hotline.Share.Enums.Push;
  15. using Hotline.Share.Tools;
  16. using Hotline.Snapshot.Interfaces;
  17. using Hotline.Users;
  18. using Mapster;
  19. using Microsoft.AspNetCore.Http;
  20. using Microsoft.Extensions.DependencyInjection;
  21. using Shouldly;
  22. using XF.Domain.Repository;
  23. namespace Hotline.Application.Tests.Domain;
  24. public class OrderVisitDomainServiceTest : TestBase
  25. {
  26. private readonly IOrderVisitDomainService _orderVisitDomainService;
  27. private readonly IOrderVisitRepository _orderVisitRepository;
  28. private readonly IRepository<OrderVisitDetail> _orderVisitDetailRepository;
  29. private readonly Publisher _publisher;
  30. private readonly IOrderRepository _orderRepository;
  31. private readonly OrderServiceMock _orderServiceMock;
  32. private readonly ISettingOrderVisitSmsReplyRuleRepository _settingOrderVisitSmsReplyRuleRepository;
  33. private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
  34. public OrderVisitDomainServiceTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IOrderVisitDomainService orderVisitDomainService, IOrderVisitRepository orderVisitRepository, IRepository<OrderVisitDetail> orderVisitDetailRepository, Publisher publisher, IOrderRepository orderRepository, OrderServiceMock orderServiceMock, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdService, IThirdAccountRepository thirdAccount, ISettingOrderVisitSmsReplyRuleRepository settingOrderVisitSmsReplyRuleRepository, ISystemDicDataCacheManager systemDicDataCacheManager) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdService, thirdAccount)
  35. {
  36. _orderVisitDomainService = orderVisitDomainService;
  37. _orderVisitRepository = orderVisitRepository;
  38. _orderVisitDetailRepository = orderVisitDetailRepository;
  39. _publisher = publisher;
  40. _orderRepository = orderRepository;
  41. _orderServiceMock = orderServiceMock;
  42. _settingOrderVisitSmsReplyRuleRepository = settingOrderVisitSmsReplyRuleRepository;
  43. _systemDicDataCacheManager = systemDicDataCacheManager;
  44. }
  45. //[Fact]
  46. public async Task UpdateSmsReplyDefault_Test()
  47. {
  48. var visit = await _orderVisitRepository
  49. .Queryable()
  50. .Where(m => m.VisitState == EVisitState.SMSVisiting)
  51. .OrderByDescending(m => m.CreationTime)
  52. .FirstAsync();
  53. visit.ShouldNotBeNull("缺少测试数据");
  54. var msg = new MessageDto()
  55. {
  56. ExternalId = visit.Id,
  57. };
  58. await _orderVisitDomainService.UpdateSmsReplyDefaultAsync(msg);
  59. var replyTxt = "默认满意";
  60. var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt("默认满意");
  61. var kv = smsReply.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
  62. var order = await _orderRepository.Queryable()
  63. .Includes(m => m.OrderVisits)
  64. .Where(m => m.OrderVisits.Any(o => o.Id == visit.Id))
  65. .FirstAsync();
  66. order.Status.ShouldBe(EOrderStatus.Visited);
  67. var visitDetail = await _orderVisitDetailRepository.Queryable()
  68. .Where(m => m.VisitId == visit.Id)
  69. .ToListAsync();
  70. foreach (var detail in visitDetail)
  71. {
  72. if (detail.VisitTarget == EVisitTarget.Seat)
  73. {
  74. var seatEvaluate = smsReply.SeatEvaluate;
  75. var voiceEvaluate = smsReply.VoiceEvaluate;
  76. detail.SeatEvaluate.ShouldBe(seatEvaluate);
  77. detail.VoiceEvaluate.ShouldBe(voiceEvaluate);
  78. }
  79. if (detail.VisitTarget == EVisitTarget.Org)
  80. {
  81. detail.OrgProcessingResults.Key.ShouldBe(kv.Key);
  82. detail.OrgProcessingResults.Value.ShouldBe(kv.Value);
  83. detail.OrgHandledAttitude.Key.ShouldBe(kv.Key);
  84. detail.OrgHandledAttitude.Value.ShouldBe(kv.Value);
  85. }
  86. }
  87. }
  88. //[Fact]
  89. public async Task OnSmsUpdate_Test()
  90. {
  91. var data = new Message() { IsSmsReply = true, SmsReplyContent = "1", PushBusiness = EPushBusiness.VisitSms };
  92. await _publisher.PublishAsync(data.Adapt<ReceiveMessageNotify>(), PublishStrategy.ParallelNoWait, new CancellationToken());
  93. }
  94. [Theory]
  95. [InlineData("4", "SMSUnsatisfied", "2", "不满意", "不满意")]
  96. [InlineData("1", "Visited", "5", "非常满意", "非常满意")]
  97. //[InlineData("非常满意", "Visited", "5", "非常满意")]
  98. [InlineData("2", "Visited", "4", "满意", "满意")]
  99. [InlineData("3", "Visited", "4", "满意", "满意")]
  100. //[InlineData("不满意", "SMSUnsatisfied", "2", "不满意")]
  101. [InlineData("5", "SMSUnsatisfied", "2", "不满意", "不满意")]
  102. [InlineData("0", "Visited", "0", "默认满意", "超过48小时自动回访")]
  103. [InlineData("都没有办理好", "SMSUnsatisfied", "", "", "都没有办理好")]
  104. public async Task UpdateSmsReply_Test(string content, string visitState, string orgResuktKey, string orgResuktValue, string visitContent)
  105. {
  106. SetZuoXi();
  107. var order = _orderServiceMock.CreateOrder()
  108. .办理到一级部门()
  109. .办理到二级部门(Set一级部门)
  110. .办理一级部门汇总(Set二级部门)
  111. .办理到归档(Set一级部门)
  112. .发布工单(SetZuoXi)
  113. .发送回访短信(SetZuoXi)
  114. .GetCreateResult();
  115. order.Id.ShouldNotBeNull();
  116. var visit = await _orderVisitRepository.Queryable()
  117. .Includes(m => m.Order)
  118. .Where(m => m.VisitState == EVisitState.SMSVisiting)
  119. .OrderByDescending(m => m.CreationTime)
  120. .FirstAsync();
  121. if (visit == null) return;
  122. visit.ShouldNotBeNull("缺少测试数据");
  123. var message = new MessageDto { ExternalId = visit.Id, IsSmsReply = true, SmsReplyContent = content, TelNumber = visit.Order.Contact };
  124. var dto = new PushReceiveMessageDto();
  125. await _orderVisitDomainService.UpdateSmsReplyAsync(message);
  126. visit = _orderVisitRepository.Get(visit.Id);
  127. visit.VisitState.ShouldBe(visitState.ToEnum<EVisitState>());
  128. visit.NowEvaluate.ShouldNotBeNull();
  129. visit.NowEvaluate.Key.ShouldBe(orgResuktKey);
  130. visit.NowEvaluate.Value.ShouldBe(orgResuktValue);
  131. var orderEntity = await _orderRepository.GetAsync(order.Id);
  132. orderEntity.ShouldNotBeNull();
  133. if (content == "4" || content == "5" || content == "不满意" || content == "非常不满意")
  134. {
  135. visit.VisitType.ShouldBeNull();
  136. orderEntity.Status.ShouldNotBe(EOrderStatus.Visited);
  137. }
  138. else
  139. {
  140. orderEntity.Status.ShouldBe(EOrderStatus.Visited);
  141. }
  142. var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt(content);
  143. await _orderVisitDetailRepository.Queryable()
  144. .Where(m => m.VisitId == visit.Id && m.VisitTarget == EVisitTarget.Org)
  145. .FirstAsync()
  146. .Then(org =>
  147. {
  148. org.OrgProcessingResults.ShouldNotBeNull();
  149. org.OrgProcessingResults.Key.ShouldBe(orgResuktKey);
  150. org.OrgProcessingResults.Value.ShouldBe(orgResuktValue);
  151. org.VisitContent.ShouldBe(visitContent);
  152. // 验证跟新工单上的字段是否成功
  153. if (new string[] { "4", "5", "不满意", "非常不满意" }.Contains(content) == false)
  154. {
  155. orderEntity.OrgProcessingResults.ShouldNotBeNull();
  156. orderEntity.OrgProcessingResults.Key.ShouldBe(orgResuktKey);
  157. orderEntity.OrgProcessingResults.Value.ShouldBe(orgResuktValue);
  158. }
  159. org.OrgHandledAttitude.ShouldNotBeNull();
  160. org.OrgHandledAttitude.Key.ShouldBe(orgResuktKey);
  161. org.OrgHandledAttitude.Value.ShouldBe(orgResuktValue);
  162. if (smsReply.IsReplyToOrgVisitContent == true)
  163. {
  164. org.VisitContent = content;
  165. }
  166. return Task.CompletedTask;
  167. });
  168. await _orderVisitDetailRepository.Queryable()
  169. .Where(m => m.VisitId == visit.Id && m.VisitTarget == EVisitTarget.Seat)
  170. .FirstAsync()
  171. .Then( seat =>
  172. {
  173. // 验证跟新工单上的字段是否成功
  174. if (new string[] { "4", "5", "不满意", "非常不满意" }.Contains(content) == true)
  175. {
  176. seat.SeatEvaluate.ShouldNotBe(ESeatEvaluate.NoSatisfied);
  177. seat.SeatEvaluate.ShouldNotBe(ESeatEvaluate.VeryNoSatisfied);
  178. seat.VoiceEvaluate.ShouldNotBe(EVoiceEvaluate.NoSatisfied);
  179. seat.VoiceEvaluate.ShouldNotBe(EVoiceEvaluate.VeryNoSatisfied);
  180. }
  181. else
  182. {
  183. if (smsReply.SeatEvaluate != null)
  184. seat.SeatEvaluate.ShouldBe(smsReply.SeatEvaluate);
  185. if (smsReply.VoiceEvaluate != null)
  186. seat.VoiceEvaluate.ShouldBe(smsReply.VoiceEvaluate);
  187. }
  188. return Task.CompletedTask;
  189. });
  190. }
  191. [Theory]
  192. [InlineData("1", "非常满意", "Visited", "VerySatisfied", "VerySatisfied", "非常满意|5")]
  193. [InlineData("2", "满意", "Visited", "Satisfied", "Satisfied", "满意|4")]
  194. [InlineData("3", "一般", "Visited", "Normal", "Normal", "满意|4")]
  195. [InlineData("4", "不满意", "SMSUnsatisfied", "NoSatisfied", "NoSatisfied", "不满意|2")]
  196. [InlineData("5", "非常不满意", "SMSUnsatisfied", "NoSatisfied", "VeryNoSatisfied", "不满意|2")]
  197. [InlineData("默认满意", "超过48小时自动回访", "Visited", "DefaultSatisfied", "DefaultSatisfied", "默认满意|0")]
  198. [InlineData("0", "超过48小时自动回访", "Visited", "DefaultSatisfied", "DefaultSatisfied", "默认满意|0")]
  199. [InlineData("1非常满意", "非常满意", "Visited", "VerySatisfied", "VerySatisfied", "非常满意|5")]
  200. public void GetVisitEvaluateByReplyTxt_Test(string replyTxt, string assertReplyTxt, string visitState, string seatEvaluate, string voiceEvaluate, string kv)
  201. {
  202. var smsReply = _orderVisitDomainService.GetVisitEvaluateByReplyTxt(replyTxt);
  203. var replyString = smsReply.VisitContent;
  204. replyString.ShouldBe(assertReplyTxt);
  205. var visitStateEnum = smsReply.VisitState;
  206. visitStateEnum.ShouldBe(visitState.ToEnum<EVisitState>());
  207. var seatEvaluateEnum = smsReply.SeatEvaluate;
  208. seatEvaluateEnum.ShouldBe(seatEvaluate.ToEnum<ESeatEvaluate>());
  209. var voiceEvaluateEnum = smsReply.VoiceEvaluate;
  210. voiceEvaluateEnum.ShouldBe(voiceEvaluate.ToEnum<EVoiceEvaluate>());
  211. var kvResult = smsReply.GetOrgProcessingResults(_systemDicDataCacheManager.VisitSatisfaction);
  212. var sp = kv.Split('|');
  213. var kV = new Kv(sp[1].ToString(), sp[0].ToString());
  214. kvResult.Key.ShouldBe(kV.Key);
  215. kvResult.Value.ShouldBe(kV.Value);
  216. }
  217. [Fact]
  218. public async Task Init_SettingOrderVisitSmsReplyRule_Data()
  219. {
  220. IEnumerable<SettingOrderVisitSmsReplyRule> entities = [
  221. new () {AppScope = "ZiGong", ReplyRegular = "1", VisitContent = "非常满意", VisitState = EVisitState.Visited, SeatEvaluate = ESeatEvaluate.VerySatisfied,VoiceEvaluate = EVoiceEvaluate.VerySatisfied,OrgProcessingResults=5, OrgHandledAttitude = 5 },
  222. new () {AppScope = "ZiGong", ReplyRegular = "2", VisitContent = "满意", VisitState = EVisitState.Visited, SeatEvaluate = ESeatEvaluate.Satisfied,VoiceEvaluate = EVoiceEvaluate.Satisfied,OrgProcessingResults=4, OrgHandledAttitude = 4 },
  223. new () {AppScope = "ZiGong", ReplyRegular = "3", VisitContent = "一般", VisitState = EVisitState.Visited, SeatEvaluate = ESeatEvaluate.Normal,VoiceEvaluate = EVoiceEvaluate.Normal,OrgProcessingResults= 4, OrgHandledAttitude = 4 },
  224. new () {AppScope = "ZiGong", ReplyRegular = "4", VisitContent = "不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = ESeatEvaluate.NoSatisfied,VoiceEvaluate = EVoiceEvaluate.NoSatisfied,OrgProcessingResults=2, OrgHandledAttitude = 2 },
  225. new () {AppScope = "ZiGong", ReplyRegular = "5", VisitContent = "非常不满意", VisitState = EVisitState.SMSUnsatisfied, SeatEvaluate = ESeatEvaluate.NoSatisfied,VoiceEvaluate = EVoiceEvaluate.VeryNoSatisfied,OrgProcessingResults=2, OrgHandledAttitude = 2 },
  226. new () {AppScope = "ZiGong", ReplyRegular = "默认满意", VisitContent = "超过48小时自动回访", VisitState = EVisitState.Visited, SeatEvaluate = ESeatEvaluate.DefaultSatisfied,VoiceEvaluate = EVoiceEvaluate.DefaultSatisfied,OrgProcessingResults=0, OrgHandledAttitude = 0 }
  227. ];
  228. foreach (var item in entities)
  229. {
  230. item.UniqueKey = (item.AppScope + item.ReplyRegular).GetMD5();
  231. if (await _settingOrderVisitSmsReplyRuleRepository.AnyAsync(m => m.UniqueKey == item.UniqueKey) == false)
  232. await _settingOrderVisitSmsReplyRuleRepository.AddAsync(item);
  233. }
  234. }
  235. }