ProcessOverviewRepository.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. using AutoMapper;
  2. using Newtonsoft.Json;
  3. using OASystem.Domain;
  4. using OASystem.Domain.Entities.Groups;
  5. using OASystem.Domain.ViewModels.JuHeExchangeRate;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace OASystem.Infrastructure.Repositories.Groups
  12. {
  13. /// <summary>
  14. /// 团组流程总览表仓储
  15. /// </summary>
  16. public class ProcessOverviewRepository : BaseRepository<Grp_ProcessOverview, Grp_ProcessOverview>
  17. {
  18. private readonly IMapper _mapper;
  19. private readonly DelegationInfoRepository _groupRep;
  20. public ProcessOverviewRepository(SqlSugarClient sqlSugar, IMapper mapper, DelegationInfoRepository groupRep) : base(sqlSugar)
  21. {
  22. _mapper = mapper;
  23. _groupRep = groupRep;
  24. }
  25. /// <summary>
  26. /// 团组流程初始化
  27. /// </summary>
  28. /// <param name="request">创建流程请求参数</param>
  29. /// <returns>创建的流程信息</returns>
  30. public async Task<Result> ProcessInitAsync(int groupId, int currUserId)
  31. {
  32. //团组验证
  33. var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(g => g.Id == groupId);
  34. if (groupInfo == null)
  35. {
  36. return new Result { Code = 400, Msg = "团组不存在" };
  37. }
  38. // 检查是否已存在流程
  39. var existingProcesses = await _sqlSugar.Queryable<Grp_ProcessOverview>().Where(p => p.GroupId == groupId).ToListAsync();
  40. if (existingProcesses.Any())
  41. {
  42. return new Result { Code = 400, Msg = "该团组的流程已存在" };
  43. }
  44. //处理签证国家
  45. var visaCountries = _groupRep.GroupSplitCountry(groupInfo.VisitCountry);
  46. // 定义默认的流程节点
  47. var processs = Grp_ProcessOverview.ProcessInit(groupId, currUserId, visaCountries);
  48. _sqlSugar.BeginTran();
  49. foreach (var item in processs)
  50. {
  51. var processId = await _sqlSugar.Insertable(item).ExecuteReturnIdentityAsync();
  52. if (processId < 1)
  53. {
  54. _sqlSugar.RollbackTran();
  55. return new Result { Code = 400, Msg = "团组流程进度总览表添加失败!" };
  56. }
  57. var nodes = item.Nodes.Select((nodeDto, index) => new Grp_ProcessNode
  58. {
  59. ProcessId = processId,
  60. NodeName = nodeDto.NodeName,
  61. NodeOrder = nodeDto.NodeOrder,
  62. OverallStatus = nodeDto.OverallStatus,
  63. //Country = nodeDto.Country,
  64. IsCurrent = nodeDto.IsCurrent,
  65. Remark = nodeDto.Remark
  66. }).ToList();
  67. var nodeIds = await _sqlSugar.Insertable(nodes).ExecuteCommandAsync();
  68. if (nodeIds < 1)
  69. {
  70. _sqlSugar.RollbackTran();
  71. return new Result { Code = 400, Msg = "团组流程进度流程表添加失败!" };
  72. }
  73. }
  74. _sqlSugar.CommitTran();
  75. return new Result { Code = 200, Msg = "添加成功!" }; ;
  76. }
  77. /// <summary>
  78. /// 获取团组的所有流程及流程详情
  79. /// </summary>
  80. /// <param name="request">创建流程请求参数</param>
  81. /// <returns>创建的流程信息</returns>
  82. public async Task<Result> ProcessesDetailsAsync(int groupId)
  83. {
  84. //团组验证
  85. var groupInfo = await _sqlSugar.Queryable<Grp_DelegationInfo>().FirstAsync(g => g.Id == groupId);
  86. if (groupInfo == null)
  87. {
  88. return new Result { Code = 400, Msg = "团组不存在" };
  89. }
  90. // 检查是否已存在流程
  91. var existingProcesses = await _sqlSugar.Queryable<Grp_ProcessOverview>().Where(p => p.GroupId == groupId).ToListAsync();
  92. if (!existingProcesses.Any())
  93. {
  94. return new Result { Code = 400, Msg = "该团组的流程不存在" };
  95. }
  96. var users = await _sqlSugar.Queryable<Sys_Users>().ToListAsync();
  97. var processData = await _sqlSugar.Queryable<Grp_ProcessOverview>()
  98. .Where(p => p.GroupId == groupId && p.IsDel == 0)
  99. .Mapper(p => p.Nodes, p => p.Nodes.First().ProcessId)
  100. .ToListAsync();
  101. var processes = processData.Select(p => new
  102. {
  103. p.Id,
  104. p.GroupId,
  105. p.ProcessType,
  106. ProcessName = p.ProcessType.GetEnumDescription(),
  107. //p.OverallStatus,
  108. //StatusText = p.OverallStatus.GetDescription(),
  109. Nodes = p.Nodes.Select(n =>
  110. {
  111. //单独处理签证板块
  112. var visaSubNodes = new List<VisaProcessNode>();
  113. string remark = string.Empty;
  114. if (p.ProcessType == GroupProcessType.Visa)
  115. {
  116. visaSubNodes = JsonConvert.DeserializeObject<List<VisaProcessNode>>(n.Remark);
  117. }
  118. return new
  119. {
  120. n.Id,
  121. n.ProcessId,
  122. n.NodeOrder,
  123. n.NodeName,
  124. n.OverallStatus,
  125. StatusText = n.OverallStatus.GetEnumDescription(),
  126. Operator = users.FirstOrDefault(u => u.Id == n.Operator)?.CnName ?? "-",
  127. OpeateTime = n.OperationTime.HasValue ? n.OperationTime.Value.ToString("yyyy-MM-dd HH:mm:ss") : "-",
  128. //节点类型为签证时使用
  129. visaSubNodes
  130. };
  131. }).OrderBy(n => n.NodeOrder).ToList()
  132. }).ToList();
  133. return new Result { Code = 200, Data = processes, Msg = "查询成功!" };
  134. }
  135. /// <summary>
  136. /// 更新节点状态
  137. /// </summary>
  138. /// <param name="nodeId">节点ID</param>
  139. /// <param name="currUserId">当前用户ID</param>
  140. /// <param name="processStatus">流程状态,默认为已完成</param>
  141. /// <returns>操作结果</returns>
  142. public async Task<Result> UpdateNodeStatusAsync(int nodeId, int currUserId, ProcessStatus processStatus = ProcessStatus.Completed)
  143. {
  144. try
  145. {
  146. // 使用事务确保数据一致性
  147. var result = await _sqlSugar.Ado.UseTranAsync(async () =>
  148. {
  149. // 1. 获取并验证节点
  150. var node = await _sqlSugar.Queryable<Grp_ProcessNode>()
  151. .FirstAsync(n => n.Id == nodeId && n.IsDel == 0);
  152. if (node == null)
  153. {
  154. throw new BusinessException("当前节点不存在或已被删除。");
  155. }
  156. // 2. 更新节点状态
  157. node.OverallStatus = processStatus;
  158. node.Operator = currUserId;
  159. node.OperationTime = DateTime.Now;
  160. var updateCount = await _sqlSugar.Updateable(node)
  161. .UpdateColumns(n => new
  162. {
  163. n.OverallStatus,
  164. n.Operator,
  165. n.OperationTime
  166. })
  167. .ExecuteCommandAsync();
  168. if (updateCount == 0)
  169. {
  170. throw new BusinessException("节点状态更新失败。");
  171. }
  172. // 3. 如果是完成当前节点,处理流程流转
  173. if (processStatus == ProcessStatus.Completed && node.IsCurrent)
  174. {
  175. await ProcessCurrentNodeCompletionAsync(node, currUserId);
  176. }
  177. return new Result { Code = StatusCodes.Status200OK, Msg = "操作成功。" };
  178. });
  179. return result.IsSuccess ? result.Data : new Result
  180. {
  181. Code = StatusCodes.Status500InternalServerError,
  182. Msg = result.ErrorMessage
  183. };
  184. }
  185. catch (BusinessException ex)
  186. {
  187. // 业务异常
  188. return new Result { Code = StatusCodes.Status400BadRequest, Msg = ex.Message };
  189. }
  190. catch (Exception ex)
  191. {
  192. // 系统异常
  193. return new Result { Code = StatusCodes.Status500InternalServerError, Msg = "系统错误,请稍后重试" };
  194. }
  195. }
  196. /// <summary>
  197. /// 处理当前节点完成后的流程流转
  198. /// </summary>
  199. private async Task ProcessCurrentNodeCompletionAsync(Grp_ProcessNode currentNode, int currUserId)
  200. {
  201. // 1. 获取流程信息
  202. var process = await _sqlSugar.Queryable<Grp_ProcessOverview>()
  203. .FirstAsync(p => p.Id == currentNode.ProcessId && p.IsDel == 0);
  204. if (process == null)
  205. {
  206. throw new BusinessException("关联的流程不存在。");
  207. }
  208. // 2. 取消当前节点的当前状态
  209. currentNode.IsCurrent = false;
  210. await _sqlSugar.Updateable(currentNode)
  211. .UpdateColumns(n => new { n.IsCurrent })
  212. .ExecuteCommandAsync();
  213. // 3. 查找并激活下一个节点
  214. var nextNode = await _sqlSugar.Queryable<Grp_ProcessNode>()
  215. .Where(n => n.ProcessId == currentNode.ProcessId
  216. && n.NodeOrder == currentNode.NodeOrder + 1
  217. && n.IsDel == 0)
  218. .FirstAsync();
  219. if (nextNode != null)
  220. {
  221. // 激活下一个节点
  222. nextNode.IsCurrent = true;
  223. nextNode.OverallStatus = ProcessStatus.InProgress;
  224. nextNode.Operator = currUserId;
  225. nextNode.OperationTime = DateTime.Now;
  226. var updateCount = await _sqlSugar.Updateable(nextNode)
  227. .UpdateColumns(n => new
  228. {
  229. n.IsCurrent,
  230. n.OverallStatus,
  231. n.Operator,
  232. n.OperationTime
  233. })
  234. .ExecuteCommandAsync();
  235. if (updateCount == 0)
  236. {
  237. throw new BusinessException("激活下一节点失败");
  238. }
  239. // 更新流程状态为进行中
  240. process.OverallStatus = ProcessStatus.InProgress;
  241. }
  242. else
  243. {
  244. // 下一节点不存在,整个流程完成
  245. process.OverallStatus = ProcessStatus.Completed;
  246. process.EndTime = DateTime.Now;
  247. }
  248. // 4. 更新流程信息
  249. process.UpdatedUserId = currUserId;
  250. process.UpdatedTime = DateTime.Now;
  251. var processUpdateCount = await _sqlSugar.Updateable(process)
  252. .UpdateColumns(p => new
  253. {
  254. p.OverallStatus,
  255. p.EndTime,
  256. p.UpdatedUserId,
  257. p.UpdatedTime
  258. })
  259. .ExecuteCommandAsync();
  260. if (processUpdateCount == 0)
  261. {
  262. throw new BusinessException("流程状态更新失败。");
  263. }
  264. }
  265. }
  266. }