Kaynağa Gözat

Merge branch 'test' of http://git.12345lm.cn/Fengwo/hotline into test

Dun.Jason 5 ay önce
ebeveyn
işleme
9baf5dcc60

+ 40 - 3
src/Hotline.Api/Controllers/KnowledgeController.cs

@@ -10,6 +10,7 @@ using Hotline.Application.Systems;
 using Hotline.Application.Tools;
 using Hotline.File;
 using Hotline.FlowEngine.WorkflowModules;
+using Hotline.FlowEngine.Workflows;
 using Hotline.KnowledgeBase;
 using Hotline.KnowledgeBase.Notifies;
 using Hotline.Permissions;
@@ -24,6 +25,7 @@ using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Knowledge;
 using Hotline.Share.Dtos.Order;
 using Hotline.Share.Enums.Article;
+using Hotline.Share.Enums.FlowEngine;
 using Hotline.Share.Enums.KnowledgeBase;
 using Hotline.Share.Mq;
 using Hotline.Share.Tools;
@@ -36,6 +38,7 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.EntityFrameworkCore.Metadata.Internal;
 using Org.BouncyCastle.Utilities.IO;
 using SqlSugar;
+using System.Text;
 using System.Threading;
 using XF.Domain.Authentications;
 using XF.Domain.Exceptions;
@@ -323,15 +326,48 @@ namespace Hotline.Api.Controllers
 
         }
 
-
         /// <summary>
         /// 批量审核
         /// </summary>
         /// <returns></returns>
         [HttpPost("batch_audit")]
-        public async Task KnowledgeBatchAuditAsync()
+        public async Task<string> KnowledgeBatchAuditAsync([FromBody] KnowledgeBatchAuditInDto dto)
         {
-            // TODO: qcy 批量审核 
+            var result = new StringBuilder();
+            var fail = 0;
+            var success = 0;
+            var nextWorkflowDto = new NextWorkflowDto
+            {
+                IsSms = dto.IsSms,
+                ReviewResult = dto.IsPass ? EReviewResult.Approval : EReviewResult.Failed,
+                Opinion = dto.Opinion
+            };
+            foreach (var knowledgeId in dto.KnowledgeIds)
+            {
+                try
+                {
+                    var knowledge = await _knowledgeDomainService.KnowledgeInfo(knowledgeId, HttpContext.RequestAborted);
+                    nextWorkflowDto.WorkflowId = knowledge.WorkflowId;
+                    var next = await _workflowApplication.GetNextStepsAsync(knowledge.WorkflowId, HttpContext.RequestAborted);
+                    nextWorkflowDto.StepId = next.StepId;
+                    nextWorkflowDto.NextStepCode = next.Steps.First().Key;
+                    nextWorkflowDto.NextStepName = next.Steps.First().Value;
+                    if (dto.IsPass)
+                        await _workflowApplication.NextAsync(nextWorkflowDto, cancellationToken: HttpContext.RequestAborted);
+                    else
+                    {
+                        var reject = nextWorkflowDto.Adapt<RejectDto>();
+                        await _workflowApplication.RejectAsync(reject, HttpContext.RequestAborted);
+                    }
+                }
+                catch (UserFriendlyException e)
+                {
+                    result.Append(e.Message);
+                    fail++;
+                }
+                success++;
+            }
+            return $"总共: {dto.KnowledgeIds.Length}, 成功: {success}, 失败: {fail}, 失败原因: {result.ToString()}";
         }
 
         /// <summary>
@@ -679,6 +715,7 @@ namespace Hotline.Api.Controllers
                 .ToPagedListAsync(pagedDto.PageIndex, pagedDto.PageSize);
             return new PagedDto<KnowledgeWorkFlowDto>(total, _mapper.Map<IReadOnlyList<KnowledgeWorkFlowDto>>(temp));
         }
+
         /// <summary>
         /// 知识查重
         /// </summary>

+ 2 - 2
src/Hotline.Api/config/appsettings.Development.json

@@ -62,13 +62,13 @@
     }
   },
   "ConnectionStrings": {
-    "Hotline": "PORT=5432;DATABASE=hotline_dev;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
+    "Hotline": "PORT=5432;DATABASE=hotline;HOST=110.188.24.182;PASSWORD=fengwo11!!;USER ID=dev;"
   },
   "Cache": {
     "Host": "110.188.24.182",
     "Port": 50179,
     "Password": "fengwo123!$!$",
-    "Database": 5 //release:3, dev:5
+    "Database": 3 //test:3, dev:5
   },
   "Swagger": true,
   "AccLog":  false,

+ 66 - 0
src/Hotline.Application.Tests/Controller/KnowledgeControllerTest.cs

@@ -0,0 +1,66 @@
+using Hotline.Api.Controllers;
+using Hotline.Api.Controllers.Bi;
+using Hotline.Application.Tests.Mock;
+using Hotline.Identity.Accounts;
+using Hotline.Identity.Roles;
+using Hotline.KnowledgeBase;
+using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Enums.KnowledgeBase;
+using Hotline.Users;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
+using Shouldly;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Application.Tests.Controller;
+public class KnowledgeControllerTest : TestBase
+{
+    private readonly KnowledgeServiceMock _knowledgeServiceMock;
+    private readonly KnowledgeController _knowledgeController;
+    private readonly IRepository<KnowledgeBase.Knowledge> _knowledgeRepository;
+
+    public KnowledgeControllerTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, KnowledgeServiceMock knowledgeServiceMock, KnowledgeController knowledgeController, IRepository<KnowledgeBase.Knowledge> knowledgeRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository)
+    {
+        _knowledgeServiceMock = knowledgeServiceMock;
+        _knowledgeController = knowledgeController;
+        _knowledgeController.ControllerContext = new ControllerContext
+        {
+            HttpContext = new DefaultHttpContext()
+        };
+        _knowledgeRepository = knowledgeRepository;
+    }
+
+    [Fact]
+    public async Task KnowledgeBatchAudit_TestAsync()
+    {
+        SetPaiDanYuan();
+        var inDto = new KnowledgeBatchAuditInDto
+        {
+            IsPass = true,
+            KnowledgeIds = new string[3],
+            IsSms = false,
+            Opinion = "批量审核通过"
+        };
+        for (int i = 0;i < 3;i++)
+        {
+            inDto.KnowledgeIds[i] = _knowledgeServiceMock.创建并审核知识()
+                .GetKnowledgeId();
+
+        }
+        Set班长();
+        await _knowledgeController.KnowledgeBatchAuditAsync(inDto);
+        foreach (var id in inDto.KnowledgeIds)
+        {
+            var k = await _knowledgeRepository.GetAsync(id);
+            k.Status.ShouldBe(EKnowledgeStatus.OnShelf);
+        }
+    }
+}

+ 2 - 0
src/Hotline.Application.Tests/Infrastructure/TestSettingConstants.cs

@@ -10,6 +10,7 @@ public static class TestSettingConstants
     public const string PaiDanYuanAccountName = "UnitTestPDY";
     public const string FirstOrgAccountName = "cs";
     public const string SecondOrgAccountName = "cs21";
+    public const string BanZhangAccountName = "UnitTestBZ";
 }
 
 public static class TestSessionConstants
@@ -23,4 +24,5 @@ public static class TestSessionConstants
     public static string UserName = "";
 
     public static string OrgId = "";
+
 }

+ 53 - 0
src/Hotline.Application.Tests/Mock/KnowledgeServiceMock.cs

@@ -0,0 +1,53 @@
+using Hotline.Api.Controllers;
+using Hotline.Application.FlowEngine;
+using Hotline.Application.Tests.Infrastructure;
+using Hotline.FlowEngine.WorkflowModules;
+using Hotline.Identity.Accounts;
+using Hotline.Share.Dtos.FlowEngine;
+using Hotline.Share.Dtos.Knowledge;
+using Hotline.Share.Enums.FlowEngine;
+using Hotline.Share.Tools;
+using Hotline.Users;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Application.Tests.Mock;
+public class KnowledgeServiceMock
+{
+    private readonly KnowledgeController _knowledgeController;
+    private string KnowledgeId;
+    private readonly IWorkflowApplication _workflowApplication;
+    private readonly IRepository<Account> _accountRepository;
+
+    public KnowledgeServiceMock(KnowledgeController knowledgeController, IWorkflowApplication workflowApplication, IRepository<Account> accountRepository)
+    {
+        _knowledgeController = knowledgeController;
+        _workflowApplication = workflowApplication;
+        _accountRepository = accountRepository;
+    }
+
+    public KnowledgeServiceMock 创建并审核知识()
+    {
+        var json = "{\"data\":{\"attribution\":\"中心知识库\",\"isPublic\":true,\"keywords\":[\"08dcfe29-01a5-4b6e-8b47-640d75aa8b23\",\"08dcfe29-01a7-4488-8412-65907c33576d\",\"08dcfe29-01a8-4217-84ae-45eda2481c9b\"],\"keywordsName\":\"张继科扥,金卡,希望\",\"knowledgeTypeId\":[\"08dc903c-aad8-4515-89f3-1ae2d6961b90\"],\"hotspotId\":\"\",\"knowledges\":[],\"files\":[],\"template\":\"\",\"content\":\"<p style=\\\"line-height: 2;\\\"><span style=\\\"font-size: 20px; font-family: 仿宋;\\\">你张继科扥金卡希望智啊</span></p>\",\"sourceOrganizeId\":\"\",\"title\":\"你张继科扥金卡希望智啊\",\"knowledgeType\":[{\"KnowledgeTypeName\":\"类型11\",\"KnowledgeTypeId\":\"08dc903c-aad8-4515-89f3-1ae2d6961b90\",\"KnowledgeTypeSpliceName\":\"类型11\"}]},\"workflow\":{\"isPass\":true,\"opinion\":\"123\",\"nextStepCode\":\"da354c75-d8f7-4c8c-af6f-1e69fb09c343\",\"nextStepName\":\"流程节点\",\"backToCountersignEnd\":false,\"nextHandlers\":[{\"userId\":\"08dc3c21-8e9b-4387-8306-6cc32d127397\",\"username\":\"班长2\",\"orgId\":\"001\",\"orgName\":\"市民热线服务中心\",\"roleId\":\"zhongxinlingdao\",\"roleName\":\"中心领导\",\"key\":\"08dc3c21-8e9b-4387-8306-6cc32d127397\",\"value\":\"班长2\"}],\"nextMainHandler\":\"08dc3c21-8e9b-4387-8306-6cc32d127397\",\"isSms\":false,\"isStartCountersign\":false,\"stepId\":null,\"nextHandler\":{},\"workflowId\":\"\",\"handlerType\":0,\"businessType\":0,\"flowDirection\":2,\"external\":{},\"files\":[]}}";
+        var inDto = json.FromJson<AddStartFlowDto>();
+        var nextStep = _workflowApplication.GetStartStepsAsync(WorkflowModuleConsts.KnowledgeAdd, CancellationToken.None).GetAwaiter().GetResult();
+        inDto.Data.Title = "单元测试" + DateTime.Now.ToString("yyyyMMddhhmmss");
+        inDto.Workflow.FlowDirection = EFlowDirection.CenterToCenter;
+        inDto.Workflow.NextStepCode = nextStep.Steps.First().Key;
+        inDto.Workflow.NextStepName = nextStep.Steps.First().Value;
+        var account = _accountRepository.GetAsync(m => m.UserName == TestSettingConstants.BanZhangAccountName).GetAwaiter().GetResult();
+        var handler = nextStep.Steps.First().Items.Where(m => m.Username == account.Name).First();
+        inDto.Workflow.NextHandlers.Add(handler);
+        KnowledgeId = _knowledgeController.AddKnowledge(inDto).GetAwaiter().GetResult();
+        return this;
+    }
+
+    public string GetKnowledgeId()
+    {
+        return KnowledgeId;
+    }
+}

+ 2 - 0
src/Hotline.Application.Tests/Startup.cs

@@ -149,11 +149,13 @@ public class Startup
             services.AddScoped<IExportApplication, ExportApplication>();
             services.AddScoped<OrderController>();
             services.AddScoped<UserController>();
+            services.AddScoped<KnowledgeController>();
             services.AddScoped<PushMessageController>();
             services.AddScoped<ISessionContext, DefaultHttpContextAccessor>();
             services.AddScoped<ISessionContextProvider, SessionContextProvider>();
             services.AddScoped<ICallApplication, XingTangCallApplication>();
             services.AddScoped<OrderServiceMock>();
+            services.AddScoped<KnowledgeServiceMock>();
             //ServiceLocator.Instance = services.BuildServiceProvider();
         }
 

+ 4 - 0
src/Hotline.Application.Tests/TestBase.cs

@@ -51,6 +51,10 @@ public class TestBase
         SetOperator("部门经办人", "测试部门/测试二级部门", "cs21", "001094001", "13408389849", EUserType.Seat, TestSettingConstants.SecondOrgAccountName);
     }
 
+    public void Set班长()
+    {
+        SetOperator("中心班长", "市民热线服务中心", "单元测试班长", "001", "13408389849", EUserType.Normal, TestSettingConstants.BanZhangAccountName);
+    }
 
     public void SetZuoXi()
     {

+ 1 - 1
src/Hotline.Application/FlowEngine/WorkflowApplication.cs

@@ -613,7 +613,7 @@ public class WorkflowApplication : IWorkflowApplication, IScopeDependency
             return dto;
         }
 
-        if (currentStep.IsInCountersign())
+        if (workflow.IsInCountersign && currentStep.IsInCountersign())
         {
             if (currentStep.IsCountersignEndStep)
             {

+ 23 - 0
src/Hotline.Share/Dtos/Knowledge/KnowledgeDto.cs

@@ -525,4 +525,27 @@ namespace Hotline.Share.Dtos.Knowledge
         /// </summary>
         public string TypeTxt => Type?.GetDescription();
     }
+
+    public class KnowledgeBatchAuditInDto
+    {
+        /// <summary>
+        /// 知识Id集合
+        /// </summary>
+        public string[] KnowledgeIds { get; set; }
+
+        /// <summary>
+        /// 是否通过
+        /// </summary>
+        public bool IsPass { get; set; }
+
+        /// <summary>
+        /// 办理意见
+        /// </summary>
+        public string Opinion { get; set; } = string.Empty;
+
+        /// <summary>
+        /// 是否短信通知
+        /// </summary>
+        public bool IsSms { get; set; }
+    }
 }

+ 5 - 1
src/Hotline/FlowEngine/Workflows/Workflow.cs

@@ -638,7 +638,11 @@ public partial class Workflow
     /// <summary>
     /// 结束流程会签状态(保留topStepId创建节点时判断用,直到下次会签开启时更新)
     /// </summary>
-    public void EndCountersign() => IsInCountersign = false;
+    public void EndCountersign()
+    {
+        IsInCountersign = false;
+        TopCountersignStepId = null;
+    }
 
     /// <summary>
     /// 重置最终办理意见

+ 21 - 22
src/Hotline/FlowEngine/Workflows/WorkflowDomainService.cs

@@ -345,8 +345,7 @@ namespace Hotline.FlowEngine.Workflows
             //结束当前会签流程
             if (currentStep.IsCountersignEndStep)
             {
-                var countersignStartStep =
-                    workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
+                var countersignStartStep = workflow.Steps.FirstOrDefault(d => d.Id == currentStep.CountersignStartStepId);
                 if (countersignStartStep is null)
                     throw new UserFriendlyException(
                         $"未查询到会签开始step, workflowId: {workflow.Id}, currentStepId: {currentStep.Id}",
@@ -406,8 +405,7 @@ namespace Hotline.FlowEngine.Workflows
                 if (!string.IsNullOrEmpty(currentStep.CountersignId))
                 {
                     //会签中正常办理节点,更新会签members办理状态
-                    var countersign =
-                        workflow.Countersigns.FirstOrDefault(d =>
+                    var countersign = workflow.Countersigns.FirstOrDefault(d =>
                             !d.IsCompleted() && d.Id == currentStep.CountersignId);
                     if (countersign is not null)
                     {
@@ -2506,12 +2504,11 @@ namespace Hotline.FlowEngine.Workflows
             newStep.IsOrigin = step.IsOrigin;
             //newStep.ParentId = step.ParentId;
             newStep.Handlers = step.Handlers;
-            //newStep.StepHandlers = _mapper.Map<List<WorkflowStepHandler>>(step.StepHandlers);
             newStep.StartCountersignId = step.StartCountersignId;
             newStep.CountersignId = step.CountersignId;
             newStep.IsStartedCountersignEnd = step.IsStartedCountersignEnd;
 
-            //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制
+            //退回场景:指派给原办理人,其余场景:按照原节点原始指派方式复制 //todo 重构为参数传入办理对象
             if (traceType is EWorkflowTraceType.Previous)
             {
                 //newStep.FlowAssignType = EFlowAssignType.User;
@@ -3115,9 +3112,7 @@ namespace Hotline.FlowEngine.Workflows
 
                 //cp会签发起节点变为待办节点
                 //1. create terminal trace 2. 撤回至startStep
-                var newStep = await DuplicateStepWithTraceAsync(workflow, startCountersignStep,
-                    EWorkflowTraceType.Normal,
-                    cancellationToken);
+                var newStep = await DuplicateStepWithTraceAsync(workflow, startCountersignStep, EWorkflowTraceType.Normal, cancellationToken);
 
                 //当topcsStep结束cs时,实际办理节点应该更新为newStep
                 if (startCountersignStep.Id == workflow.TopCountersignStepId)
@@ -3128,7 +3123,9 @@ namespace Hotline.FlowEngine.Workflows
                             UserId = startCountersignStep.HandlerId,
                             Username = startCountersignStep.HandlerName,
                             OrgId = startCountersignStep.HandlerOrgId,
-                            OrgName = startCountersignStep.HandlerOrgName
+                            OrgName = startCountersignStep.HandlerOrgName,
+                            RoleId = startCountersignStep.RoleId,
+                            RoleName = startCountersignStep.RoleName
                         });
 
                     workflow.UpdateCurrentStepWhenAssign(newStep,
@@ -3137,25 +3134,27 @@ namespace Hotline.FlowEngine.Workflows
                             UserId = startCountersignStep.HandlerId,
                             Username = startCountersignStep.HandlerName,
                             OrgId = startCountersignStep.HandlerOrgId,
-                            OrgName = startCountersignStep.HandlerOrgName
+                            OrgName = startCountersignStep.HandlerOrgName,
+                            RoleId = startCountersignStep.RoleId,
+                            RoleName = startCountersignStep.RoleName
                         });
                 }
 
-                //csEndStep又开启了cs,在结束会签时,如果该节点是topcs的end节点, workflow.topcsStep应该更新为前一cs开启stepId
-                if (startCountersignStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
-                    workflow.TopCountersignStepId = startCountersignStep.CountersignStartStepId;
+                // //csEndStep又开启了cs,在结束会签时,如果该节点是topcs的end节点, workflow.topcsStep应该更新为前一cs开启stepId
+                // if (startCountersignStep.IsTopCountersignEndStep(workflow.TopCountersignStepId))
+                //     workflow.TopCountersignStepId = startCountersignStep.CountersignStartStepId;
 
                 if (workflow.CheckIfCountersignOver())
                     workflow.EndCountersign();
 
-                var removeHandlers = updateSteps.SelectMany(d => d.Handlers).Select(d => d.Key).ToList();
-
-                var handlerObjs = newStep.Handlers.Select(d => new HandlerGroupItem
-                {
-                    GroupId = Guid.NewGuid().ToString(),
-                    Key = d.Key,
-                    Value = d.Value
-                }).ToList();
+                // var removeHandlers = updateSteps.SelectMany(d => d.Handlers).Select(d => d.Key).ToList();
+                //
+                // var handlerObjs = newStep.Handlers.Select(d => new HandlerGroupItem
+                // {
+                //     GroupId = Guid.NewGuid().ToString(),
+                //     Key = d.Key,
+                //     Value = d.Value
+                // }).ToList();
                 //workflow.UpdateHandlers(removeHandlers, newStep.FlowAssignType.Value, handlerObjs);
 
                 await _workflowRepository.UpdateAsync(workflow, cancellationToken);