using Hotline.CallCenter.Calls; using Hotline.File; using Hotline.FlowEngine.Workflows; using Hotline.Settings.Hotspots; using Hotline.Share.Dtos; using Hotline.Share.Dtos.File; using Hotline.Share.Enums.FlowEngine; using Hotline.Share.Enums.Order; using Hotline.Share.Enums.Settings; using Hotline.Users; using SqlSugar; using System.ComponentModel; using XF.Domain.Exceptions; using XF.Domain.Extensions; using XF.Domain.Repository; using XF.Utility.EnumExtensions; namespace Hotline.Orders { /// /// 工单 /// [Description("工单")] [SugarIndex("unique_order_no", nameof(Order.No), OrderByType.Desc, true)] [SugarIndex("index_order_creationtime", nameof(Order.CreationTime), OrderByType.Asc)] [SugarIndex("index_order_startTime", nameof(Order.StartTime), OrderByType.Asc)] public partial class Order : PositionWorkflowEntity { public Order() { //HotspotCodeLv1 ??= HotspotCode?[..2]; } /// /// 第一次评价结果 /// public string? FirstVisitResult { get; set; } public string? FirstVisitResultCode { get; set; } #region 来电信息 /// /// 来源渠道(电话、网站、APP等) /// public string? SourceChannel { get; set; } public string? SourceChannelCode { get; set; } /// /// 渠道为电话时,此字段存在(Call.Id) /// public string? CallId { get; set; } /// /// 来电归属地 /// public string? CallAddress { get; set; } /// /// 来电号码 /// public string? FromPhone { get; set; } /// /// 转接号码(转接来源) /// public string? TransferPhone { get; set; } /// /// 来电/信人姓名 /// public string? FromName { get; set; } /// /// 来电/信人性别 /// public EGender FromGender { get; set; } /// /// 来电/信人身份 /// public EIdentityType? IdentityType { get; set; } /// /// 证件类型 /// public string? LicenceTypeCode { get; set; } public string? LicenceType { get; set; } /// /// 证件号码 /// public string? LicenceNo { get; set; } /// /// 年龄段 /// public string? AgeRangeCode { get; set; } public string? AgeRange { get; set; } /// /// 联系电话 /// [SugarColumn(ColumnDescription = "联系电话", IsNullable = true)] public string? Contact { get; set; } [SugarColumn(ColumnDescription = "联系电话脱敏", IsNullable = true)] public string? ContactMask { get; set; } /// /// 是否接受短信,勾选校验手机号 /// public bool AcceptSms { get; set; } /// /// 是否已发送短信 /// public bool SmsSended { get; set; } /// /// 是否保密 /// public bool IsSecret { get; set; } /// /// 工作单位(当“来电/信人身份”为“企业”时必填,其他情况非必填) /// [SugarColumn(ColumnDescription = "工作单位", IsNullable = true)] public string? Company { get; set; } #endregion #region 诉求信息 /// /// 受理类型 /// public string? AcceptType { get; set; } public string? AcceptTypeCode { get; set; } /// /// 紧急程度 /// public EEmergencyLevel EmergencyLevel { get; set; } = EEmergencyLevel.Normal; public string Title { get; set; } #region 热点 /// /// 热点 /// public string? HotspotId { get; set; } //public string? HotspotCode { get; set; } //public string? HotspotCodeLv1 { get; set; } public string? HotspotName { get; set; } public string? HotspotSpliceName { get; set; } /// /// 外部数据(为前端提供级联功能) /// public string? HotspotExternal { get; set; } #endregion #region 事件分类 public string? EventCategoryId { get; set; } public string? EventCategoryName { get; set; } public string? EventCategorySpliceName { get; set; } public string? EventCategoryExternal { get; set; } #endregion /// /// 事发时间 /// public DateTime? IncidentTime { get; set; } /// /// 事件目的 /// public string? IncidentPurpose { get; set; } /// /// 重复工单Id /// [SugarColumn(ColumnDescription = "重复工单Id", ColumnDataType = "json", IsJson = true)] public List? DuplicateIds { get; set; } /// /// 推送分类 /// public string? PushTypeCode { get; set; } public string? PushType { get; set; } /// /// 附件 /// [SugarColumn(ColumnDataType = "json", IsJson = true)] public List? Additions { get; set; } = new(); /// /// 诉求内容 /// [SugarColumn(ColumnDataType = "varchar(2000)")] public string Content { get; set; } #endregion #region 工单属性 /// /// 工单状态 /// public EOrderStatus Status { get; set; } /// /// 过期状态 //todo 延迟消息更新此字段 /// public EExpiredStatus ExpiredStatus { get; set; } /// /// 来源,区分省平台或110等其他平台同步过来的工单 /// public ESource Source { get; set; } /// /// 处理方式(直办、交办) /// public EProcessType ProcessType { get; set; } = EProcessType.Zhiban; ///// ///// 进展情况 ///// //[SugarColumn(DefaultValue = "0")] //public EProgress Progress { get; set; } /// /// 是否公开 /// public bool IsPublicity { get; set; } /// /// 是否为省工单(省派发工单非政民互动直派的为省工单) /// public bool IsProvince { get; set; } /// /// 工单编码(20220101000001) /// public string? No { get; set; } /// /// 是否已撤销 /// public bool IsCancel { get; set; } /// /// 市民查询密码 /// public string? Password { get; set; } /// /// 企业名称 /// public string? EnterpriseName { get; set; } /// /// 企业Code /// public string? EnterpriseCode { get; set; } /// /// 专班名称 /// public string? ZhuanBanMingCheng { get; set; } /// /// 专班Code /// public string? ZhuanBanCode { get; set; } #endregion #region 流程信息 /// /// 工单开始时间(受理/接办时间=流程开启时间) /// public DateTime? StartTime { get; set; } /// /// 超期时间(期满时间) /// public DateTime? ExpiredTime { get; set; } /// /// 即将超期时间 /// public DateTime? NearlyExpiredTime { get; set; } /// /// 交办时间(中心交部门办理时间) /// public DateTime? CenterToOrgTime { get; set; } /// /// 交办意见 /// public string? CenterToOrgOpinion { get; set; } /// /// 交办人 /// public string? CenterToOrgHandlerId { get; set; } public string? CenterToOrgHandlerName { get; set; } /// /// 归档时间(暂为流程结束时间,因流程结束自动归档) /// public DateTime? FiledTime { get; set; } /// /// 办结时长(秒) /// 办结时间-交办时间 /// public double? HandleDuration { get; set; } /// /// 办结工作日时长(秒) /// public double? HandleDurationWorkday { get; set; } /// /// 归档时长(秒) /// 归档时间-交办时间 /// public double? FileDuration { get; set; } /// /// 归档工作时长(秒) /// public double? FileDurationWorkday { get; set; } /// /// 全流程时长(秒) /// 归档时间-创建时间 /// public double? AllDuration { get; set; } public double? AllDurationWorkday { get; set; } /// /// 办理时间限制(如:24小时、7个工作日) /// public string? TimeLimit { get; set; } public int? TimeLimitCount { get; set; } public ETimeType? TimeLimitUnit { get; set; } #region 会签实际办理对象 [SugarColumn(ColumnDataType = "json", IsJson = true)] public List? CsActualHandleOrgIds { get; set; } [SugarColumn(ColumnDataType = "json", IsJson = true)] public List? CsActualHandleUserIds { get; set; } #endregion #region 实际办理信息(节点,部门,意见) /// /// 实际办理节点code(会签状态此字段保存最外层会签发起节点code) /// public string? ActualHandleStepCode { get; set; } /// /// 实际办理节点名称(会签状态此字段保存最外层会签发起节点名称) /// public string? ActualHandleStepName { get; set; } /// /// 到达实际办理节点时间(stepBox创建时间) /// public DateTime? ActualHandleStepCreateTime { get; set; } /// /// 实际办理节点签收时间 /// public DateTime? ActualHandleStepAcceptTime { get; set; } /// /// 实际办理时间 /// public DateTime? ActualHandleTime { get; set; } /// /// 实际办理人id /// public string? ActualHandlerId { get; set; } /// /// 实际办理人名称 /// public string? ActualHandlerName { get; set; } /// /// 实际办理部门名称 /// public string? ActualHandleOrgName { get; set; } /// /// 实际办理部门编码 /// public string? ActualHandleOrgCode { get; set; } /// /// 实际办理部门行政区划编码 /// public string? ActualHandleOrgAreaCode { get; set; } /// /// 实际办理部门行政区划名称 /// public string? ActualHandleOrgAreaName { get; set; } ///// ///// 实际办理对象(会签停留在顶级发起节点) ///// 办理时选择的办理对象,可能是部门也可能是用户 ///// //public string? ActualHandlerValue { get; set; } //public string? ActualHandlerKey { get; set; } //public EHandlerType? ActualHandlerType { get; set; } /// /// 实际办理意见(办理中...or 最终办理意见) /// [SugarColumn(Length = 2000)] public string ActualOpinion { get; set; } = "办理中..."; /// /// 真实办理人姓名(手动填写) /// public string? RealHandlerName { get; set; } /// /// 真实办理人电话(手动填写) /// public string? RealHandlerPhone { get; set; } /// /// 沟通方式(手动填写) /// public ERealCommunicationMode? RealCommunicationMode { get; set; } /// /// 沟通时间(手动填写) /// public DateTime? RealCommunicationTime { get; set; } /// /// 沟通地点(手动填写) /// public string? RealCommunicationAddress { get; set; } /// /// 已与市民沟通 /// public bool? RealIsContacted { get; set; } /// /// 已与市民现场沟通 /// public bool? RealContactLocale { get; set; } #endregion #region 当前办理节点信息 ///// ///// 当前办理节点code(非会签:当前被指派节点,会签:会签发起节点) ///// //public string? CurrentStepCode { get; set; } ///// ///// 当前节点名称 ///// //public string? CurrentStepName { get; set; } ///// ///// 到达当前节点时间 ///// //public DateTime? CurrentStepCreateTime { get; set; } ///// ///// 当前办理节点签收时间 ///// //public DateTime? CurrentHandleStepAcceptTime { get; set; } ///// ///// 当前办理时间 ///// //public DateTime? CurrentHandleTime { get; set; } ///// ///// 当前办理人id ///// //public string? CurrentHandlerId { get; set; } ///// ///// 当前办理人名称 ///// //public string? CurrentHandlerName { get; set; } ///// ///// 当前办理部门名称 ///// //public string? CurrentHandleOrgName { get; set; } ///// ///// 当前办理部门编码 ///// //public string? CurrentHandleOrgCode { get; set; } ///// ///// 当前办理部门行政区划编码 ///// //public string? CurrentHandleOrgAreaCode { get; set; } ///// ///// 当前办理部门行政区划名称 ///// //public string? CurrentHandleOrgAreaName { get; set; } #endregion #region 一级部门 /// /// 一级部门code /// [SugarColumn(IsNullable = true)] public string? OrgLevelOneCode { get; set; } /// /// 一级部门名称 /// [SugarColumn(IsNullable = true)] public string? OrgLevelOneName { get; set; } #endregion #region 二级部门 /// /// 二级部门code /// [SugarColumn(IsNullable = true)] public string? OrgLevelTwoCode { get; set; } /// /// 二级部门名称 /// [SugarColumn(IsNullable = true)] public string? OrgLevelTwoName { get; set; } #endregion #region 受理人(开启流程的话务员) /// /// 受理人id /// public string? AcceptorId { get; set; } /// /// 受理人名称 /// public string? AcceptorName { get; set; } /// /// 受理人工号 /// public string? AcceptorStaffNo { get; set; } /// /// 受理人部门编码 /// public string? AcceptorOrgCode { get; set; } /// /// 受理人部门名称 /// public string? AcceptorOrgName { get; set; } #endregion #region 派单人 /// /// 派单次数 /// public int? SendOrderNumber { get; set; } = 0; #endregion /// /// 会签类型 /// public ECounterSignType? CounterSignType { get; set; } #region 签收 /// /// 签收人id /// public string? SignerId { get; set; } /// /// 签收人名称 /// public string? SignerName { get; set; } #endregion #region 归档冗余字段 /// /// 归档人名称 /// public string? FileUserName { get; set; } /// /// 归档人ID /// public string? FileUserId { get; set; } /// /// 归档人部门Id /// public string? FileUserOrgId { get; set; } /// /// 归档人部门名称 /// public string? FileUserOrgName { get; set; } /// /// 归档人类型 /// public EFileUserType? FileUserRole { get; set; } /// /// 归档意见 /// [SugarColumn(ColumnDataType = "varchar(2000)")] public string? FileOpinion { get; set; } #endregion #endregion #region 省工单字段 /// /// 省期满时间(省工单才有) /// public DateTime? ExpiredTimeProvince { get; set; } /// /// 同步省工单编号和省上传下来的工单都用这个字段 /// public string? ProvinceNo { get; set; } /// /// 外部工单唯一标识 /// public string? ExternalId { get; set; } /// /// 工单标签 /// public string? TagNames { get; set; } #endregion #region 附件冗余 [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)] public List? FileJson { get; set; } #endregion #region 市州工单互转 /// /// 是否转发 /// public bool? Transpond { get; set; } /// /// 转发市州Id /// public string? TranspondCityId { get; set; } /// /// 转发市州名称 /// public string? TranspondCityName { get; set; } /// /// 转发市州Value /// public string? TranspondCityValue { get; set; } #endregion #region 重办 /// /// 重办次数 /// public int? ReTransactNum { get; set; } #endregion /// /// 敏感标签 /// [SugarColumn(ColumnDataType = "json", IsJson = true, IsNullable = true)] public List? Sensitive { get; set; } /// /// 是否行政执法类 /// public bool? IsEnforcementOrder { get; set; } /// /// 部门是否解决 /// [SugarColumn(DefaultValue = "f")] public bool IsResolved { get; set; } /// /// 待发布人Id /// public string? WaitForPublisherId { get; set; } } public partial class Order { /// /// 受理人 /// [Navigate(NavigateType.OneToOne, nameof(AcceptorId))] public User Acceptor { get; set; } /// /// 热点 /// [Navigate(NavigateType.OneToOne, nameof(HotspotId))] public Hotspot Hotspot { get; set; } /// /// 办理流程 /// [Navigate(NavigateType.OneToOne, nameof(WorkflowId))] public Workflow Workflow { get; set; } /// /// 工单扩展信息 /// [Navigate(NavigateType.OneToOne, nameof(Id))] public OrderExtension OrderExtension { get; set; } /// /// 已发布工单 /// [Navigate(NavigateType.OneToOne, nameof(Id),nameof(Orders.OrderPublish.OrderId))] public OrderPublish OrderPublish { get; set; } /// /// 已回访工单 /// [Navigate(NavigateType.OneToMany, nameof(OrderVisit.OrderId))] public List OrderVisits { get; set; } /// /// 甄别 /// [Navigate(NavigateType.OneToMany, nameof(OrderScreen.OrderId))] public List OrderScreens { get; set; } /// /// /// [Navigate(NavigateType.OneToMany, nameof(OrderSpecial.OrderId))] public List OrderSpecials { get; set; } /// /// 延期 /// [Navigate(NavigateType.OneToMany, nameof(OrderDelay.OrderId))] public List OrderDelays { get; set; } /// /// 工单补充 /// [Navigate(NavigateType.OneToMany, nameof(OrderComplement.OrderId))] public List OrderComplements { get; set; } /// /// 通话记录 /// //[Navigate(NavigateType.OneToOne, nameof(CallId), nameof(TrCallRecord.CallAccept))] //由CallAccept改成OtherAccept [Navigate(NavigateType.OneToOne, nameof(CallId), nameof(TrCallRecord.OtherAccept))] public TrCallRecord CallRecord { get; set; } #region Method public void Cancel() { IsCancel = true; } public void Redo() { Status = EOrderStatus.Handling; ExpiredStatus = EExpiredStatus.Normal; } public void CheckIfFiled() { if (Status is EOrderStatus.Filed) throw UserFriendlyException.SameMessage("工单已归档"); } public void Init() { if (!string.IsNullOrEmpty(Contact)) ContactMask = Contact.MaskPhoneNumber(); Status = EOrderStatus.WaitForAccept; ExpiredStatus = EExpiredStatus.Normal; } public void AutoAccept(string userId, string? userName, string? staffNo) { AcceptorId = userId; AcceptorName = userName; AcceptorStaffNo = staffNo; } /// /// 开始工单办理流程 /// public void StartManageFlow() => Status = EOrderStatus.Handling; /// /// 更新工单办理中状态 /// public void UpdateHandlingStatus(bool isInCountersign) => Status = isInCountersign ? EOrderStatus.Countersigning : EOrderStatus.Handling; /// /// 归档 /// public void File(DateTime filedTime, double handleDurationWorkday, double fileDurationWorkday, double allDurationWorkday) { if (Status is EOrderStatus.Filed) return; Status = EOrderStatus.Filed; FiledTime = filedTime; HandleDurationWorkday = handleDurationWorkday; FileDurationWorkday = fileDurationWorkday; AllDurationWorkday = allDurationWorkday; //计算实际办结时长 SetHandleDuration(); SetFileDuration(); SetAllDuration(); } /// /// 发布 /// /// public void Publish(bool isPublicity) { //Progress = EProgress.Published; Status = EOrderStatus.Published; IsPublicity = isPublicity; } /// /// 已回访 /// public void Visited(string resultCode, string result) { if (string.IsNullOrEmpty(resultCode) || string.IsNullOrEmpty(result)) return; if (!string.IsNullOrEmpty(FirstVisitResultCode)) return; FirstVisitResultCode = resultCode; FirstVisitResult = result; //Progress = EProgress.Visited; Status = EOrderStatus.Visited; } public void CenterToOrg(string timelimit, int timelimitCount, ETimeType timilimitUnit, DateTime expiredTime, DateTime nearlyExpiredTime, string opinion, string handlerId, string handlerName, bool canUpdateOrderSender) { ProcessType = EProcessType.Jiaoban; TimeLimit = timelimit; TimeLimitCount = timelimitCount; TimeLimitUnit = timilimitUnit; ExpiredTime = expiredTime; if (canUpdateOrderSender) { CenterToOrgTime = DateTime.Now; CenterToOrgOpinion = opinion; CenterToOrgHandlerId = handlerId; CenterToOrgHandlerName = handlerName; } NearlyExpiredTime = nearlyExpiredTime; SendOrderNumber += 1; if (string.IsNullOrEmpty(WaitForPublisherId)) WaitForPublisherId = handlerId; } public void OrgToCenter(string timelimit, int timelimitCount, ETimeType timilimitUnit, DateTime expiredTime, DateTime nearlyExpiredTime) { ProcessType = EProcessType.Zhiban; TimeLimit = timelimit; TimeLimitCount = timelimitCount; TimeLimitUnit = timilimitUnit; ExpiredTime = expiredTime; NearlyExpiredTime = nearlyExpiredTime; CenterToOrgTime = null; CenterToOrgOpinion = null; CenterToOrgHandlerId = null; CenterToOrgHandlerName = null; } public void CenterToCenter(string timelimit, int timelimitCount, ETimeType timilimitUnit, DateTime expiredTime, DateTime nearlyExpiredTime) { TimeLimit = timelimit; TimeLimitCount = timelimitCount; TimeLimitUnit = timilimitUnit; ExpiredTime = expiredTime; NearlyExpiredTime = nearlyExpiredTime; } public void SetHandleDuration() { if (!ActualHandleTime.HasValue) return; if (!CenterToOrgTime.HasValue) return; HandleDuration = Math.Round((ActualHandleTime - CenterToOrgTime).Value.TotalSeconds); } public void SetAllDuration() { if (!FiledTime.HasValue) return; if (!StartTime.HasValue) return; AllDuration = Math.Round((FiledTime - StartTime).Value.TotalSeconds); } public void SetFileDuration() { if (!FiledTime.HasValue) return; if (!CenterToOrgTime.HasValue) return; FileDuration = Math.Round((FiledTime - CenterToOrgTime).Value.TotalSeconds); } /// /// 是否已签收 /// public bool IsSigned() => !string.IsNullOrEmpty(SignerId); /// /// 签收 /// public void Sign(string userId, string userName) { if (string.IsNullOrEmpty(SignerId)) { SignerId = userId; SignerName = userName; } } ///// ///// 返回未签收状态 ///// //public void BackToUnsign() //{ // SignerId = string.Empty; // SignerName = string.Empty; //} #endregion } public class UnsignedOrder { public Order Order { get; set; } public WorkflowStep WorkflowStep { get; set; } } }