Jelajahi Sumber

合并处理

TANG JIANG 2 tahun lalu
induk
melakukan
8fb9bc6c04

+ 100 - 3
src/Hotline.Api/Controllers/OrderController.cs

@@ -1,23 +1,39 @@
-using Hotline.Orders;
+using Hotline.Application.FlowEngine;
+using Hotline.FlowEngine.Workflows;
+using Hotline.Orders;
 using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Share.Dtos;
+using Hotline.Share.Dtos.FlowEngine;
 using Hotline.Share.Dtos.Order;
+using Hotline.Share.Enums.Order;
 using Hotline.Share.Requests;
 using MapsterMapper;
 using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Authentications;
+using XF.Domain.Exceptions;
+using XF.Domain.Extensions;
 
 namespace Hotline.Api.Controllers;
 
 public class OrderController : BaseController
 {
+    private readonly IOrderDomainService _orderDomainService;
     private readonly IOrderRepository _orderRepository;
+    private readonly IWorkflowApplication _workflowApplication;
+    private readonly IWorkflowDomainService _workflowDomainService;
     private readonly IMapper _mapper;
 
     public OrderController(
+        IOrderDomainService orderDomainService,
         IOrderRepository orderRepository,
+        IWorkflowApplication workflowApplication,
+        IWorkflowDomainService workflowDomainService,
         IMapper mapper)
     {
+        _orderDomainService = orderDomainService;
         _orderRepository = orderRepository;
+        _workflowApplication = workflowApplication;
+        _workflowDomainService = workflowDomainService;
         _mapper = mapper;
     }
 
@@ -27,12 +43,93 @@ public class OrderController : BaseController
     /// <param name="dto"></param>
     /// <returns></returns>
     [HttpGet]
-    public async Task<PagedDto<OrderDto>> Query(PagedKeywordRequest dto)
+    public async Task<PagedDto<OrderDto>> Query([FromQuery] QueryOrderDto dto)
     {
         var (total, items) = await _orderRepository.Queryable()
-            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Title.Contains(dto.Keyword) || x.No.Contains(dto.Keyword))
+            .Includes(d => d.Employee)
+            .Includes(d => d.Workflow, d => d.Assigns)
+            .WhereIF(!string.IsNullOrEmpty(dto.Keyword), d => d.Title.Contains(dto.Keyword) || d.No.Contains(dto.Keyword))
+            .WhereIF(!string.IsNullOrEmpty(dto.Content), d => d.Content.Contains(dto.Content))
+            .WhereIF(dto.AcceptType.HasValue, d => d.AcceptType == dto.AcceptType)
+            .WhereIF(dto.Channel.HasValue, d => d.Channel == dto.Channel)
+            .WhereIF(!string.IsNullOrEmpty(dto.HotspotId), d => d.HotspotId == dto.HotspotId)
+            .WhereIF(!string.IsNullOrEmpty(dto.TransferPhone), d => d.TransferPhone.Contains(dto.TransferPhone))
+            .WhereIF(!string.IsNullOrEmpty(dto.OrgCode), d => d.Workflow.Assigns.Any(x => x.OrgCode == dto.OrgCode))
+            .WhereIF(!string.IsNullOrEmpty(dto.NameOrNo), d => d.Employee.Name.Contains(dto.NameOrNo) || d.Employee.StaffNo.Contains(dto.NameOrNo))
+            .WhereIF(dto.CreationTimeStart.HasValue, d => d.CreationTime >= dto.CreationTimeStart)
+            .WhereIF(dto.CreationTimeEnd.HasValue, d => d.CreationTime <= dto.CreationTimeEnd)
+            .WhereIF(dto.EmergencyLevel.HasValue, d => d.EmergencyLevel == dto.EmergencyLevel)
+            .WhereIF(!string.IsNullOrEmpty(dto.PhoneNo), d => d.FromPhone.Contains(dto.PhoneNo) || d.Contact.Contains(dto.PhoneNo))
+            .WhereIF(dto.PushType.HasValue, d => d.PushType == dto.PushType)
+            .WhereIF(dto.ExpiredTimeStart.HasValue, d => d.ExpiredTime >= dto.ExpiredTimeStart)
+            .WhereIF(dto.ExpiredTimeEnd.HasValue, d => d.ExpiredTime <= dto.ExpiredTimeEnd)
+            .WhereIF(dto.Status.HasValue, d => d.Status == dto.Status)
             .ToPagedListAsync(dto.PageIndex, dto.PageSize);
 
         return new PagedDto<OrderDto>(total, _mapper.Map<IReadOnlyList<OrderDto>>(items));
     }
+
+    [HttpGet("{id}")]
+    public async Task<OrderDto> Get(string id)
+    {
+        var order = await _orderRepository.Queryable()
+            .Includes(d => d.OrderComplain)
+            .FirstAsync(d => d.Id == id);
+        order.Workflow = await _workflowDomainService.GetWorkflowAsync(order.WorkflowId,
+            withSupplements: true, cancellationToken: HttpContext.RequestAborted);
+
+        return _mapper.Map<OrderDto>(order);
+    }
+
+    [HttpPost]
+    public async Task<string> Add([FromBody] AddOrderDto dto)
+    {
+        var order = _mapper.Map<Order>(dto);
+        return await _orderDomainService.AddAsync(order, HttpContext.RequestAborted);
+    }
+
+    [HttpDelete("{id}")]
+    public async Task Remove(string id)
+    {
+        var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
+        if (order == null) return;
+        if (order.Status != EOrderStatus.Temporary)
+            throw UserFriendlyException.SameMessage("非草稿工单不可删除");
+        await _orderRepository.RemoveAsync(order);
+    }
+
+    [HttpPut]
+    public async Task Update([FromBody] UpdateOrderDto dto)
+    {
+        var order = await _orderRepository.GetAsync(dto.Id, HttpContext.RequestAborted);
+        if (order == null)
+            throw UserFriendlyException.SameMessage("无效工单编号");
+        if (order.Status != EOrderStatus.Temporary)
+            throw UserFriendlyException.SameMessage("非草稿工单不可编辑");
+        await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+    }
+
+    [HttpPost("{id}/startflow")]
+    public async Task StartFlow(string id, [FromBody] StartWorkflowDto dto)
+    {
+        var order = await _orderRepository.GetAsync(id, HttpContext.RequestAborted);
+        if (order == null)
+            throw UserFriendlyException.SameMessage("无效工单编号");
+        if (order.Status != EOrderStatus.Temporary || !string.IsNullOrEmpty(order.WorkflowId))
+            throw UserFriendlyException.SameMessage("工单已发起流程");
+        var workflowId = await _workflowApplication.StartWorkflowAsync(dto, HttpContext.RequestAborted);
+        order.WorkflowId = workflowId;
+        await _orderRepository.UpdateAsync(order, HttpContext.RequestAborted);
+    }
+
+    [HttpGet("base-data")]
+    public dynamic BaseData()
+    {
+        return new
+        {
+            //ModuleOptions = WorkflowModule.Modules.ToList(),
+            //GenderOptions = EnumExts.GetDescriptions<EHandlerType>(),
+            //CountersignMode = EnumExts.GetDescriptions<ECountersignMode>().Where(d => d.Key != 1)
+        };
+    }
 }

+ 4 - 4
src/Hotline.Application/Handlers/FlowEngine/NextStepHandler.cs

@@ -32,11 +32,9 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
                 var order = await _orderRepository.GetAsync(d => d.WorkflowId == workflow.Id, cancellationToken);
                 if (order == null)
                     throw new UserFriendlyException($"工单审批流程Id无效, workflowId: {workflow.Id}", "无效流程编号");
-                order.Assign(notification.FlowAssignType, data.Handlers.Select(d=>d.Id));
-
-                //todo business logic
-
                 if (order.Status is EOrderStatus.Filed) return;
+                
+                order.Assign(notification.FlowAssignType, data.Handlers.Select(d=>d.Id));
                 //1.如果order未处于会签中,则判断是否发起会签(isstartCountersign) 2.如果处于会签中,则判断会签是否结束(isCountersignEnd)
                 if (order.Status is EOrderStatus.Countersigning && notification.IsCountersignEnd)
                 {
@@ -49,6 +47,8 @@ public class NextStepHandler : INotificationHandler<NextStepNotify>
 
                 order.CurrentStepTime = workflow.CurrentStepTime;
                 order.CurrentStepName = workflow.CurrentStepName;
+
+                await _orderRepository.UpdateAsync(order, cancellationToken);
                 break;
 
             //case WorkflowModuleConsts.KnowledgeAdd:

+ 251 - 0
src/Hotline.Share/Dtos/Order/OrderComplainDto.cs

@@ -0,0 +1,251 @@
+using Hotline.Share.Enums.Order;
+
+namespace Hotline.Share.Dtos.Order;
+
+public class OrderComplainDto : OrderExtensionDto
+{
+    #region 投诉详情
+
+    /// <summary>
+    /// 投诉问题类别
+    /// </summary>
+    public string ComplainClassifyCode { get; set; }
+
+    public string ComplainClassify { get; set; }
+
+    /// <summary>
+    /// 争议发生时间
+    /// </summary>
+    public DateTime OccurrenceTime { get; set; }
+
+    /// <summary>
+    /// 投诉目标,销售方式为“网购”时展示该字段且必填
+    /// </summary>
+    public EOrderTarget? ComplainTarget { get; set; }
+
+    /// <summary>
+    /// 经营地址,销售方式为“现场”时必填
+    /// </summary>
+    //todo 地址信息不够完善
+    public string? BussinessArea { get; set; }
+
+    public string? BussinessAddress { get; set; }
+
+    /// <summary>
+    /// 诉求类型,多选
+    /// </summary>
+    public EComplainType? ComplainType { get; set; }
+
+    #endregion
+}
+
+public class OrderExtensionDto
+{
+    #region 投诉人信息
+
+    /// <summary>
+    /// 证件类型
+    /// </summary>
+    public string? LicenceTypeCode { get; set; }
+
+    public string? LicenceType { get; set; }
+
+    /// <summary>
+    /// 证件号码, 证件类型已选的情况为必填,否则非必填
+    /// </summary>
+    public string? LicenceNo { get; set; }
+
+    /// <summary>
+    /// 提供方类型(投诉人类型)
+    /// </summary>
+    public EProviderType? ProviderType { get; set; }
+
+    /// <summary>
+    /// 提供方身份(投诉人身份)
+    /// </summary>
+    public ECitizenStatus1? ProviderStatus { get; set; }
+
+    /// <summary>
+    /// 国籍或地区
+    /// </summary>
+    public ENationality? Nationality { get; set; }
+
+    /// <summary>
+    /// 民族
+    /// </summary>
+    public string? NationCode { get; set; }
+
+    public string? Nation { get; set; }
+
+    /// <summary>
+    /// 邮政编码
+    /// </summary>
+    public string? PostalCode { get; set; }
+
+    /// <summary>
+    /// 邮箱
+    /// </summary>
+    public string? Email { get; set; }
+
+    /// <summary>
+    /// 其他联系方式
+    /// </summary>
+    public string? OtherContact { get; set; }
+
+    #endregion
+
+    #region 投诉对象信息
+
+    /// <summary>
+    /// 企业名称
+    /// </summary>
+    public string EnterpriseName { get; set; }
+
+    /// <summary>
+    /// 统一社会信用代码
+    /// </summary>
+    public string? UnifiedSocialCreditCode { get; set; }
+
+    /// <summary>
+    /// 注册地址
+    /// </summary>
+    public string RegisterAddress { get; set; }
+
+    /// <summary>
+    /// 注册号
+    /// </summary>
+    public string? RegisterNumber { get; set; }
+
+    /// <summary>
+    /// 企业联系人
+    /// </summary>
+    public string? EnterpriseContact { get; set; }
+
+    /// <summary>
+    /// 市场主体类型
+    /// </summary>
+    public string? MarketTypeCode { get; set; }
+
+    public string? MarketType { get; set; }
+
+    /// <summary>
+    /// 行业分类
+    /// </summary>
+    public string? IndustryClassifyCode { get; set; }
+
+    public string? IndustryClassify { get; set; }
+
+    #endregion
+
+    #region 投诉/举报 详情
+
+
+    /// <summary>
+    /// 商品分类/品牌
+    /// </summary>
+    public string BrandCode { get; set; }
+
+    public string Brand { get; set; }
+
+    /// <summary>
+    /// 消费金额,只能填写数字,且只能填写非负数
+    /// </summary>
+    public decimal Amount { get; set; }
+
+    /// <summary>
+    /// 客体类别
+    /// </summary>
+    public string ObjectClassifyCode { get; set; }
+
+    public string ObjectClassify { get; set; }
+
+    /// <summary>
+    /// 销售方式
+    /// </summary>
+    public ESalesMode SalesMode { get; set; }
+
+    /// <summary>
+    /// 电商平台,销售方式为“网购”时展示该字段且必填
+    /// </summary>
+    public string? ECommercePlatformCode { get; set; }
+
+    public string? ECommercePlatform { get; set; }
+
+    /// <summary>
+    /// 外部订单号,销售方式为“ 网购”时展示该字段且必填
+    /// </summary>
+    public string? ExternalOrderNo { get; set; }
+
+    /// <summary>
+    /// 具体渠道
+    /// <remarks>
+    /// 销售方式为“电视购物”“电话购物”“邮购”时展示该字段,且必填
+    /// 电视购物:请填写购物的电视频道
+    /// 电话购物:请填写商品销售者的热线号码
+    /// 邮购:请填写宣传商品的邮政公司或来件地址
+    /// </remarks>
+    /// </summary>
+    public string? Channel { get; set; }
+
+    /// <summary>
+    /// 专利权人,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    public string? Patentee { get; set; }
+
+    /// <summary>
+    /// 专利名称,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    public string? PatentName { get; set; }
+
+    /// <summary>
+    /// 专利类型,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    public EPatentType? PatentType { get; set; }
+
+    /// <summary>
+    /// 专利号,“投诉问题类别”为“专利”时展示该字段,选填
+    /// </summary>
+    public string? PatentNo { get; set; }
+
+    /// <summary>
+    /// 产品名称
+    /// </summary>
+    public string? ProductName { get; set; }
+
+    /// <summary>
+    /// 批准文号
+    /// </summary>
+    public string? ApprovalNumber { get; set; }
+
+    /// <summary>
+    /// 产品批号
+    /// </summary>
+    public string? ProductBatchNo { get; set; }
+
+    /// <summary>
+    /// 产品规格
+    /// </summary>
+    public string? ProductStandard { get; set; }
+
+    /// <summary>
+    /// 产品有效期
+    /// </summary>
+    public DateTime ProductExpriedTime { get; set; }
+
+    /// <summary>
+    /// 生产厂家
+    /// </summary>
+    public string? Manufacturer { get; set; }
+
+    /// <summary>
+    /// 销售企业
+    /// </summary>
+    public string? SalesEnterprise { get; set; }
+
+    /// <summary>
+    /// 消费者地址
+    /// </summary>
+    public string? ConsumerAddress { get; set; }
+
+    #endregion
+}

+ 211 - 0
src/Hotline.Share/Dtos/Order/OrderDto.cs

@@ -3,12 +3,95 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using Hotline.Share.Enums.Order;
+using XF.Utility.EnumExtensions;
 
 namespace Hotline.Share.Dtos.Order
 {
     public class OrderDto : UpdateOrderDto
     {
+        #region 工单属性
+
+        /// <summary>
+        /// 当前节点名称
+        /// </summary>
+        public string CurrentStepName { get; set; }
+
+        /// <summary>
+        /// 到达当前节点时间
+        /// </summary>
+        public DateTime CurrentStepTime { get; set; }
+
+        /// <summary>
+        /// 工单状态
+        /// </summary>
+        public EOrderStatus Status { get; set; }
+
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public DateTime? StartTime { get; set; }
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public DateTime? ExpiredTime { get; set; }
+
+        /// <summary>
+        /// 过期状态
+        /// </summary>
+        public EExpiredStatus ExpiredStatus { get; set; }
+
+        #endregion
+
         public string CreationTime { get; set; }
+
+        public string StatusText => Status.GetDescription();
+
+        public string? ContactMask { get; set; }
+
+        /// <summary>
+        /// 工单编码(202201010001)
+        /// </summary>
+        public string No { get; set; }
+
+        public string? DuplicateName { get; set; }
+
+        public string AcceptTypeText => AcceptType.GetDescription();
+        public string EmergencyLevelText => EmergencyLevel.GetDescription();
+
+        /// <summary>
+        /// 受理人姓名
+        /// </summary>
+        public string EmployeeName { get; set; }
+
+        /// <summary>
+        /// 受理人工号
+        /// </summary>
+        public string? EmployeeStaffNo { get; set; }
+
+        /// <summary>
+        /// 超期时间描述(需求:超期3天、0.5天后超期)
+        /// </summary>
+        public string ExpiredText => CalculateExpiredText();
+
+        private string CalculateExpiredText()
+        {
+            //todo 完整处理方案:1.创建待过期表,Id,过期时间,即将过期时间等字段。2.延迟消息通知处理过期,删除子表数据,处理order过期状态字段。3.此处即可采用expiredStatus进行判断
+            //todo 目前暂时采用过期时间计算
+            if (!ExpiredTime.HasValue)
+                return string.Empty;
+            var days = (DateTime.Now - ExpiredTime.Value).TotalDays;
+            switch (days)
+            {
+                case > 0:
+                    return $"超期{days:N1}天";
+                case < 0:
+                    return $"{days:N1}天后超期";
+                default:
+                    return "超期不到1天";
+            }
+        }
     }
 
     public class UpdateOrderDto : AddOrderDto
@@ -18,5 +101,133 @@ namespace Hotline.Share.Dtos.Order
 
     public class AddOrderDto
     {
+        #region 来电信息
+
+        /// <summary>
+        /// 来源渠道
+        /// </summary>
+        public EChannel Channel { get; set; }
+
+        ///// <summary>
+        ///// 接线员工(userId)
+        ///// </summary>
+        //public string EmployeeId { get; set; }
+
+        /// <summary>
+        /// 来电号码
+        /// </summary>
+        public string? FromPhone { get; set; }
+
+        /// <summary>
+        /// 转接号码(转接来源)
+        /// </summary>
+        public string? TransferPhone { get; set; }
+
+        /// <summary>
+        /// 来电/信人姓名
+        /// </summary>
+        public string FromName { get; set; }
+
+        /// <summary>
+        /// 来电/信人性别
+        /// </summary>
+        public EGender FromGender { get; set; }
+
+        /// <summary>
+        /// 来电/信人身份
+        /// </summary>
+        public ECitizenStatus FromStatus { get; set; }
+
+        /// <summary>
+        /// 证件类型
+        /// </summary>
+        public ELicenceType? Licence { get; set; }
+
+        /// <summary>
+        /// 证件号码
+        /// </summary>
+        public string? LicenceNo { get; set; }
+
+        /// <summary>
+        /// 年龄段
+        /// </summary>
+        public EAgeRange? AgeRange { get; set; }
+
+        /// <summary>
+        /// 联系电话
+        /// </summary>
+        public string? Contact { get; set; }
+
+        /// <summary>
+        /// 是否接受短信,勾选校验手机号
+        /// </summary>
+        public bool AcceptSms { get; set; }
+
+        /// <summary>
+        /// 是否需要联系
+        /// </summary>
+        public bool NeedContact { get; set; }
+
+        /// <summary>
+        /// 工作单位(当“来电/信人身份”为“企业”时必填,其他情况非必填)
+        /// </summary>
+        public string? Company { get; set; }
+
+        #endregion
+
+        #region 诉求信息
+
+        /// <summary>
+        /// 工单类型
+        /// </summary>
+        public EOrderType OrderType { get; set; }
+
+        /// <summary>
+        /// 受理类型
+        /// </summary>
+        public EAcceptType AcceptType { get; set; }
+
+        /// <summary>
+        /// 紧急程度
+        /// </summary>
+        public EEmergencyLevel EmergencyLevel { get; set; } = EEmergencyLevel.Normal;
+
+        public string Title { get; set; }
+
+        /// <summary>
+        /// 热点
+        /// </summary>
+        public string HotspotId { get; set; }
+        public string Hotspot { get; set; }
+        public string HotspotSpliceName { get; set; }
+
+        /// <summary>
+        /// 事发时间
+        /// </summary>
+        public DateTime? IncidentTime { get; set; }
+
+        /// <summary>
+        /// 重复工单
+        /// </summary>
+        public string? DuplicateId { get; set; }
+
+        /// <summary>
+        /// 推送分类
+        /// </summary>
+        public EPushType PushType { get; set; }
+
+        /// <summary>
+        /// 附件
+        /// </summary>
+        public List<string> Additions { get; set; } = new();
+
+        /// <summary>
+        /// 诉求内容
+        /// </summary>
+        public string Content { get; set; }
+
+        #endregion
+
+        public OrderComplainDto OrderComplain { get; set; }
     }
 }

+ 43 - 2
src/Hotline.Share/Dtos/Order/QueryOrderDto.cs

@@ -34,7 +34,48 @@ namespace Hotline.Share.Dtos.Order
         /// <summary>
         /// 热点分类
         /// </summary>
-        public string HotspotId { get; set; }
-        
+        public string? HotspotId { get; set; }
+
+        /// <summary>
+        /// 接办部门
+        /// </summary>
+        public string? OrgCode { get; set; }
+
+        /// <summary>
+        /// 受理坐席名字或工号
+        /// </summary>
+        public string? NameOrNo { get; set; }
+
+        /// <summary>
+        /// 受理时间(工单创建时间)
+        /// </summary>
+        public DateTime? CreationTimeStart { get; set; }
+        public DateTime? CreationTimeEnd { get; set; }
+
+        /// <summary>
+        /// 紧急程度
+        /// </summary>
+        public EEmergencyLevel? EmergencyLevel { get; set; }
+
+        /// <summary>
+        /// 来电或联系电话
+        /// </summary>
+        public string? PhoneNo { get; set; }
+
+        /// <summary>
+        /// 推送分类
+        /// </summary>
+        public EPushType? PushType { get; set; }
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public DateTime? ExpiredTimeStart { get; set; }
+        public DateTime? ExpiredTimeEnd { get; set; }
+
+        /// <summary>
+        /// 工单状态
+        /// </summary>
+        public EOrderStatus? Status { get; set; }
     }
 }

+ 6 - 0
src/Hotline.Share/Enums/Order/ECitizenStatus1.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum ECitizenStatus1
+{
+    //城镇、农村、港澳台同胞、外籍、军人、学生、其他
+}

+ 7 - 0
src/Hotline.Share/Enums/Order/EComplainType.cs

@@ -0,0 +1,7 @@
+namespace Hotline.Share.Enums.Order;
+
+[Flags]
+public enum EComplainType
+{
+    //修理、重做、更换、退货、补足商品数量、退赔费用、赔偿损失、停止侵权、核定侵权责任
+}

+ 19 - 0
src/Hotline.Share/Enums/Order/EExpiredStatus.cs

@@ -0,0 +1,19 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum EExpiredStatus
+{
+    /// <summary>
+    /// 正常状态(未超期)
+    /// </summary>
+    Normal = 0,
+
+    /// <summary>
+    /// 即将超期
+    /// </summary>
+    GoingToExpired = 1,
+
+    /// <summary>
+    /// 已超期
+    /// </summary>
+    Expired = 2,
+}

+ 6 - 0
src/Hotline.Share/Enums/Order/ENationality.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum ENationality
+{
+    //中国、外国、港澳台地区
+}

+ 6 - 0
src/Hotline.Share/Enums/Order/EOrderTarget.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum EOrderTarget
+{
+    //平台、入驻商家
+}

+ 6 - 0
src/Hotline.Share/Enums/Order/EPatentType.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum EPatentType
+{
+    //发明专利、实用新型专利、外观设计专利
+}

+ 6 - 0
src/Hotline.Share/Enums/Order/EProviderType.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum EProviderType
+{
+    //生产企业、销售企业、服务企业、其他企业、个体工商户、自然人、群诉、其他类型
+}

+ 6 - 0
src/Hotline.Share/Enums/Order/ESalesMode.cs

@@ -0,0 +1,6 @@
+namespace Hotline.Share.Enums.Order;
+
+public enum ESalesMode
+{
+    //网购、现场、电视购物、电话购物、邮购
+}

+ 5 - 0
src/Hotline/Orders/IOrderDomainService.cs

@@ -9,5 +9,10 @@ namespace Hotline.Orders
     public interface IOrderDomainService
     {
         Task<string> AddAsync(Order order, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// 归档
+        /// </summary>
+        Task FileAsync(string workflowId, CancellationToken cancellationToken);
     }
 }

+ 28 - 25
src/Hotline/Orders/Order.cs

@@ -1,6 +1,8 @@
-using Hotline.Share.Enums.Order;
+using Hotline.FlowEngine.Workflows;
+using Hotline.Share.Enums.Order;
 using Hotline.Users;
 using SqlSugar;
+using XF.Domain.Extensions;
 using XF.Domain.Repository;
 
 namespace Hotline.Orders
@@ -18,7 +20,7 @@ namespace Hotline.Orders
         public EChannel Channel { get; set; }
 
         /// <summary>
-        /// 接线员工
+        /// 接线员工(userId)
         /// </summary>
         public string EmployeeId { get; set; }
 
@@ -87,12 +89,6 @@ namespace Hotline.Orders
         [SugarColumn(ColumnDescription = "工作单位", IsNullable = true)]
         public string? Company { get; set; }
 
-        /// <summary>
-        /// 接线员(服务人)
-        /// </summary>
-        [Navigate(NavigateType.OneToOne, nameof(EmployeeId))]
-        public User Employee { get; set; }
-
         #endregion
 
         #region 诉求信息
@@ -148,12 +144,13 @@ namespace Hotline.Orders
         /// <summary>
         /// 附件
         /// </summary>
-        [SugarColumn(ColumnDataType = "varchar(2000)", IsJson = true)]
+        [SugarColumn(ColumnDataType = "varchar(1000)", IsJson = true)]
         public List<string> Additions { get; set; } = new();
 
         /// <summary>
         /// 诉求内容
         /// </summary>
+        [SugarColumn(ColumnDataType = "varchar(2000)")]
         public string Content { get; set; }
 
         #endregion
@@ -163,12 +160,13 @@ namespace Hotline.Orders
         /// <summary>
         /// 当前节点名称
         /// </summary>
-        public string CurrentStepName { get; set; }
+        [SugarColumn(ColumnDescription = "当前节点名称", IsNullable = true)]
+        public string? CurrentStepName { get; set; }
 
         /// <summary>
         /// 到达当前节点时间
         /// </summary>
-        public DateTime CurrentStepTime { get; set; }
+        public DateTime? CurrentStepTime { get; set; }
 
         /// <summary>
         /// 工单状态
@@ -191,24 +189,15 @@ namespace Hotline.Orders
         public EExpiredStatus ExpiredStatus { get; set; }
 
         #endregion
-    }
-
-    public enum EExpiredStatus
-    {
-        /// <summary>
-        /// 正常状态(未超期)
-        /// </summary>
-        Normal = 0,
 
         /// <summary>
-        /// 即将超期
+        /// 接线员(服务人)
         /// </summary>
-        GoingToExpired = 1,
+        [Navigate(NavigateType.OneToOne, nameof(EmployeeId))]
+        public User Employee { get; set; }
 
-        /// <summary>
-        /// 已超期
-        /// </summary>
-        Expired = 2,
+        [Navigate(NavigateType.OneToOne, nameof(WorkflowId))]
+        public Workflow Workflow { get; set; }
     }
 
     /// <summary>
@@ -221,5 +210,19 @@ namespace Hotline.Orders
         /// </summary>
         [Navigate(NavigateType.OneToOne, nameof(Id))]
         public OrderComplain OrderComplain { get; set; }
+
+        #region Method
+
+        public void Init(string employeeId)
+        {
+            EmployeeId = employeeId;
+            if (!string.IsNullOrEmpty(Contact))
+                ContactMask = Contact.MaskPhoneNumber();
+            Status = EOrderStatus.Temporary;
+            ExpiredStatus = EExpiredStatus.Normal;
+            StartTime = DateTime.Now;
+        }
+
+        #endregion
     }
 }

+ 2 - 37
src/Hotline/Orders/OrderComplain.cs

@@ -1,4 +1,5 @@
-using SqlSugar;
+using Hotline.Share.Enums.Order;
+using SqlSugar;
 using XF.Domain.Repository;
 
 namespace Hotline.Orders;
@@ -42,40 +43,4 @@ public class OrderComplain : OrderExtensionEntity
     public EComplainType? ComplainType { get; set; }
 
     #endregion
-}
-
-[Flags]
-public enum EComplainType
-{
-    //修理、重做、更换、退货、补足商品数量、退赔费用、赔偿损失、停止侵权、核定侵权责任
-}
-
-public enum EPatentType
-{
-    //发明专利、实用新型专利、外观设计专利
-}
-
-public enum ENationality
-{
-    //中国、外国、港澳台地区
-}
-
-public enum ECitizenStatus1
-{
-    //城镇、农村、港澳台同胞、外籍、军人、学生、其他
-}
-
-public enum EProviderType
-{
-    //生产企业、销售企业、服务企业、其他企业、个体工商户、自然人、群诉、其他类型
-}
-
-public enum EOrderTarget
-{
-    //平台、入驻商家
-}
-
-public enum ESalesMode
-{
-    //网购、现场、电视购物、电话购物、邮购
 }

+ 31 - 7
src/Hotline/Orders/OrderDomainService.cs

@@ -1,33 +1,55 @@
-using XF.Domain.Cache;
+using Hotline.Share.Enums.Order;
+using XF.Domain.Authentications;
+using XF.Domain.Cache;
+using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Extensions;
 
 namespace Hotline.Orders;
 
-public class OrderDomainService : IOrderDomainService
+public class OrderDomainService : IOrderDomainService, IScopeDependency
 {
     private const string OrderNoPrefix = "OrderNo:";
     private readonly IOrderRepository _orderRepository;
     private readonly ITypedCache<int> _cacheOrderNo;
+    private readonly ISessionContext _sessionContext;
 
     public OrderDomainService(
         IOrderRepository orderRepository,
-        ITypedCache<int> cacheOrderNo)
+        ITypedCache<int> cacheOrderNo,
+        ISessionContext sessionContext)
     {
         _orderRepository = orderRepository;
         _cacheOrderNo = cacheOrderNo;
+        _sessionContext = sessionContext;
     }
 
     public async Task<string> AddAsync(Order order, CancellationToken cancellationToken)
     {
-        if (!string.IsNullOrEmpty(order.Contact))
-            order.ContactMask = order.Contact.MaskPhoneNumber();
-
+        order.Init(_sessionContext.RequiredUserId);
         order.No = GenerateNewOrderNo();
+        //order.ExpiredTime = Calculate();//todo 根据配置获取办理时长再计算过期时间
+
+        await _orderRepository.AddNav(order)
+            .Include(d => d.OrderComplain)
+            .ExecuteCommandAsync();
+        return order.Id;
+    }
 
-        return await _orderRepository.AddAsync(order, cancellationToken);
+    /// <summary>
+    /// 归档
+    /// </summary>
+    public async Task FileAsync(string workflowId, CancellationToken cancellationToken)
+    {
+        var order = await _orderRepository.GetAsync(d => d.WorkflowId == workflowId, cancellationToken);
+        if (order == null)
+            throw UserFriendlyException.SameMessage("无效的工单编号");
+        order.Status = EOrderStatus.Filed;
+        await _orderRepository.UpdateAsync(order, cancellationToken);
     }
 
+    #region private
+
     private string GenerateNewOrderNo()
     {
         var today = DateTime.Today;
@@ -50,4 +72,6 @@ public class OrderDomainService : IOrderDomainService
     {
         return $"{today:yyyyMMdd}{count.ToString("000000")}";
     }
+
+    #endregion
 }

+ 3 - 1
src/Hotline/Orders/OrderExtensionEntity.cs

@@ -1,4 +1,5 @@
-using SqlSugar;
+using Hotline.Share.Enums.Order;
+using SqlSugar;
 using XF.Domain.Repository;
 
 namespace Hotline.Orders;
@@ -147,6 +148,7 @@ public class OrderExtensionEntity : FullStateEntity
     /// </summary>
     [SugarColumn(IsNullable = true)]
     public string? ECommercePlatformCode { get; set; }
+
     [SugarColumn(IsNullable = true)]
     public string? ECommercePlatform { get; set; }
 

+ 2 - 1
src/Hotline/Orders/OrderReport.cs

@@ -1,4 +1,5 @@
-using SqlSugar;
+using Hotline.Share.Enums.Order;
+using SqlSugar;
 
 namespace Hotline.Orders;