瀏覽代碼

完成特殊红包功能

qinchaoyue 2 月之前
父節點
當前提交
289f80e6d7

+ 36 - 25
src/Hotline.Api/Controllers/Snapshot/RedPackController.cs

@@ -9,6 +9,9 @@ using Hotline.Caching.Interfaces;
 using XF.Utility.EnumExtensions;
 using Hotline.Share.Enums.Snapshot;
 using Quartz.Impl.Triggers;
+using Hotline.Orders;
+using XF.Domain.Exceptions;
+using Mapster;
 
 namespace Hotline.Api.Controllers.Snapshot;
 
@@ -19,14 +22,16 @@ public class RedPackController : BaseController
     private readonly ISystemDicDataCacheManager _sysDic;
     private readonly ISnapshotSMSTemplateRepository _snapshotSMSTemplateRepository;
     private readonly IOrderSnapshotRepository _orderSnapshotRepository;
+    private readonly IOrderRepository _orderRepository;
 
-    public RedPackController(IRedPackApplication redPackApplication, IIndustryRepository industryRepository, ISystemDicDataCacheManager sysDic, ISnapshotSMSTemplateRepository snapshotSMSTemplateRepository, IOrderSnapshotRepository orderSnapshotRepository)
+    public RedPackController(IRedPackApplication redPackApplication, IIndustryRepository industryRepository, ISystemDicDataCacheManager sysDic, ISnapshotSMSTemplateRepository snapshotSMSTemplateRepository, IOrderSnapshotRepository orderSnapshotRepository, IOrderRepository orderRepository)
     {
         _redPackApplication = redPackApplication;
         _industryRepository = industryRepository;
         _sysDic = sysDic;
         _snapshotSMSTemplateRepository = snapshotSMSTemplateRepository;
         _orderSnapshotRepository = orderSnapshotRepository;
+        _orderRepository = orderRepository;
     }
 
     #region 特殊红包
@@ -38,6 +43,25 @@ public class RedPackController : BaseController
     [HttpGet("special")]
     public async Task<PagedDto<SnapshotOrderAuditItemsOutDto>> GetRedPackSpecialItems([FromQuery] SnapshotOrderAuditItemsInDto dto)
         => (await _redPackApplication.GetRedPackSpecialAuditItems(dto).ToPagedListAsync(dto)).ToPaged();
+
+    /// <summary>
+    /// 特殊红包审核通过或拒绝
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPut("audit/special")]
+    public async Task UpdateRedPackSpecialAuditAsync([FromBody] UpdateRedPackSpecialAuditInDto dto)
+        => await _redPackApplication.AuditRedPackSpecialAuditAsync(dto);
+
+    /// <summary>
+    /// 特殊红包审核详情信息(OrderId)
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("audit/special/{id}")]
+    public async Task<SnapshotOrderAuditSpecialDetailOutDto> GetRedPackSpecialAuditBaseDataAsync(string id)
+    {
+        return await _redPackApplication.GetRedPackSpecialAuditBaseDataAsync(id);
+    }
     #endregion
 
     #region 红包审核
@@ -121,31 +145,9 @@ public class RedPackController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpGet("record/basedata/{id}")]
-    public async Task<Dictionary<string, object>> UpdateRedPackRecordBaseDataAsync(string id)
+    public async Task<GetRedPackRecordBaseDataOutDto> UpdateRedPackRecordBaseDataAsync(string id)
     {
-        var snapshot = await _orderSnapshotRepository.Queryable()
-            .Where(m => m.Id == id)
-            .Select(m => new
-            {
-                m.Id,
-                m.AwardBankCardNo,
-                m.AwardOpenBank,
-                m.AwardName,
-                m.AwardAmount
-            })
-            .FirstAsync();
-        var dic = new Dictionary<string, object>()
-        {
-            { "replenishType", _sysDic.SnapshotReplenishType }
-        };
-        if (snapshot != null)
-        {
-            dic.Add("bankCardNo", snapshot.AwardBankCardNo);
-            dic.Add("openBank", snapshot.AwardOpenBank);
-            dic.Add("name", snapshot.AwardName);
-            dic.Add("amount", snapshot.AwardAmount);
-        }
-        return dic;
+        return await _redPackApplication.GetRedPackRecordBaseDataAsync(id); ;
     }
 
     /// <summary>
@@ -157,6 +159,15 @@ public class RedPackController : BaseController
     public async Task UpdateRedPackRecordAsync([FromBody] UpdateRedPackRecordInDto dto)
         => await _redPackApplication.UpdateRedPackRecordAsync(dto);
 
+    /// <summary>
+    /// 添加补充发放信息(特殊红包)
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    [HttpPut("record/special")]
+    public async Task UpdateRedPackSpecialRecordAsync([FromBody] UpdateRedPackRecordInDto dto)
+        => await _redPackApplication.UpdateRedPackSpecialRecordAsync(dto);
+
     /// <summary>
     /// 补充发放集合基础信息
     /// </summary>

+ 1 - 1
src/Hotline.Api/Controllers/Snapshot/SnapshotController.cs

@@ -91,7 +91,7 @@ public class SnapshotController : BaseController
     /// </summary>
     /// <returns></returns>
     [HttpPost("order")]
-    [LogFilter("添加随手拍工单")]
+    [LogFilterAlpha("添加随手拍工单")]
     public async Task<AddSnapshotOrderOutDto> AddOrderAsync([FromBody] AddSnapshotOrderInDto dto)
     {
         var ssp = _systemDicDataCacheManager.SourceChannel.FirstOrDefault(m => m.DicDataName == "随手拍")

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

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

+ 23 - 0
src/Hotline.Application/Snapshot/IRedPackApplication.cs

@@ -23,6 +23,7 @@ public interface IRedPackApplication
     /// <param name="dto"></param>
     /// <returns></returns>
     Task AuditRedPackGuiderAuditAsync(UpdateRedPackGuiderAuditInDto dto);
+    Task AuditRedPackSpecialAuditAsync(UpdateRedPackSpecialAuditInDto dto);
 
     /// <summary>
     /// 获取特提参数
@@ -65,6 +66,14 @@ public interface IRedPackApplication
     /// <returns></returns>
     ISugarQueryable<SnapshotOrderGuiderAuditItemsOutDto> GetRedPackGuiderAuditItems(SnapshotOrderGuiderAuditItemsInDto dto);
 
+    /// <summary>
+    /// 获取补充发放记录基础数据
+    /// </summary>
+    /// <param name="v"></param>
+    /// <param name="orderId"></param>
+    /// <returns></returns>
+    Task<GetRedPackRecordBaseDataOutDto> GetRedPackRecordBaseDataAsync(string orderId);
+
     /// <summary>
     /// 红包发放明细
     /// </summary>
@@ -86,6 +95,13 @@ public interface IRedPackApplication
     ISugarQueryable<SnapshotRedPackRecordItemsOutDto> GetRedPackRecordItems(SnapshotRedPackRecordItemsInDto dto);
     ISugarQueryable<SnapshotRedPackRecordSupplementItemsOutDto> GetRedPackRecordSupplementItems(SnapshotRedPackRecordSupplementItemsInDto dto);
 
+    /// <summary>
+    /// 特殊红包审核详情信息
+    /// </summary>
+    /// <param name="id"></param>
+    /// <returns></returns>
+    Task<SnapshotOrderAuditSpecialDetailOutDto> GetRedPackSpecialAuditBaseDataAsync(string id);
+
     /// <summary>
     /// 特殊红包审批集合
     /// </summary>
@@ -106,4 +122,11 @@ public interface IRedPackApplication
     /// <param name="dto"></param>
     /// <returns></returns>
     Task UpdateRedPackRecordAsync(UpdateRedPackRecordInDto dto);
+
+    /// <summary>
+    /// 添加补充发放信息(特殊红包)
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    Task UpdateRedPackSpecialRecordAsync(UpdateRedPackRecordInDto dto);
 }

+ 127 - 10
src/Hotline.Application/Snapshot/RedPackApplication.cs

@@ -1,4 +1,6 @@
-using Hotline.Orders;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using Hotline.Caching.Interfaces;
+using Hotline.Orders;
 using Hotline.Push.FWMessage;
 using Hotline.Share.Attributes;
 using Hotline.Share.Dtos;
@@ -21,6 +23,7 @@ using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Repository;
 using XF.Utility.EnumExtensions;
+using static NPOI.SS.Format.CellNumberFormatter;
 
 namespace Hotline.Application.Snapshot;
 public class RedPackApplication : IRedPackApplication, IScopeDependency
@@ -29,6 +32,7 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     private readonly IOrderRepository _orderRepository;
     private readonly ISnapshotSMSTemplateRepository _snapshotSMSTemplateRepository;
     private readonly IIndustryRepository _industryRepository;
+    private readonly ISpecialRedPackAuditRepository _specialRedPackAuditRepository;
 
     /// <summary>
     /// 市民红包审核仓储
@@ -42,8 +46,9 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     private readonly ISupplementRecordRepository _supplementRecordRepository;
     private readonly IPushDomainService _pushDomainService;
     private readonly ILogger<RedPackApplication> _logger;
+    private readonly ISystemDicDataCacheManager _systemDic;
 
-    public RedPackApplication(IOrderSnapshotRepository orderSnapshotRepository, ISnapshotSMSTemplateRepository snapshotSMSTemplateRepository, IOrderRepository orderRepository, IIndustryRepository industryRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, IRepository<OrderSpecial> orderSpecialRepository, ISessionContext sessionContext, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IThirdAccountRepository thirdAccountRepository, ISupplementRecordRepository supplementRecordRepository, IPushDomainService pushDomainService, ILogger<RedPackApplication> logger)
+    public RedPackApplication(IOrderSnapshotRepository orderSnapshotRepository, ISnapshotSMSTemplateRepository snapshotSMSTemplateRepository, IOrderRepository orderRepository, IIndustryRepository industryRepository, IRedPackAuditRepository redPackAuditRepository, IRedPackRecordRepository redPackRecordRepository, IRepository<OrderSpecial> orderSpecialRepository, ISessionContext sessionContext, IRedPackGuiderAuditRepository redPackGuiderAuditRepository, IThirdAccountRepository thirdAccountRepository, ISupplementRecordRepository supplementRecordRepository, IPushDomainService pushDomainService, ILogger<RedPackApplication> logger, ISpecialRedPackAuditRepository specialRedPackAuditRepository, ISystemDicDataCacheManager systemDic)
     {
         _orderSnapshotRepository = orderSnapshotRepository;
         _snapshotSMSTemplateRepository = snapshotSMSTemplateRepository;
@@ -58,6 +63,8 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         _supplementRecordRepository = supplementRecordRepository;
         _pushDomainService = pushDomainService;
         _logger = logger;
+        _specialRedPackAuditRepository = specialRedPackAuditRepository;
+        _systemDic = systemDic;
     }
 
     /// <summary>
@@ -74,8 +81,13 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         if (redPackAudit.Status != ERedPackAuditStatus.Pending) throw UserFriendlyException.SameMessage("已审核, 不可重复审核");
         redPackAudit.SMSTemplateId = dto.SMSTemplateId;
         redPackAudit.Status = status;
-        redPackAudit.Remark = dto.Opinion;
+        redPackAudit.AuditRemark = dto.Opinion;
         redPackAudit.IsSendSMS = dto.IsSendSms;
+        redPackAudit.AuditId = _sessionContext.UserId;
+        redPackAudit.AuditName = _sessionContext.UserName;
+        redPackAudit.AuditTime = DateTime.Now;
+        redPackAudit.AuditOrgId = _sessionContext.OrgId;
+        redPackAudit.AuditOrgName = _sessionContext.OrgName;
         var order = await _orderRepository.Queryable()
             .Where(m => m.Id == redPackAudit.OrderId)
             .Select(m => new { m.Id, m.No, m.FromName, m.FromPhone })
@@ -241,19 +253,20 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
     /// </summary>
     /// <param name="dto"></param>
     /// <returns></returns>
-    /// <exception cref="NotImplementedException"></exception>
     [ExportExcel("特殊红包审批")]
     public ISugarQueryable<SnapshotOrderAuditItemsOutDto> GetRedPackSpecialAuditItems(SnapshotOrderAuditItemsInDto dto)
     {
-        ERedPackAuditStatus? status = null;
-        if (dto.Status != -1 && Enum.TryParse<ERedPackAuditStatus>(dto.Status.ToString(), out var statusParse))
-        {
-            status = statusParse;
-        }
+        var beginTime = new DateTime(2024, 8, 1);
+        var endTime = new DateTime(2024, 9, 30, 23, 59, 59);
         var query = _redPackAuditRepository.Queryable()
             .LeftJoin<OrderSnapshot>((redPackAudit, snapshot) => redPackAudit.OrderId == snapshot.Id)
             .LeftJoin<Order>((redPackAudit, snapshot, order) => redPackAudit.OrderId == order.Id)
-            .Where((redPackAudit, snapshot, order) => snapshot.IndustryName == "安全隐患" && order.OrderTagCode.Contains("DHZY"))
+            .LeftJoin<SpecialRedPackAudit>((redPackAudit, snapshot, order, special) => redPackAudit.OrderId == special.OrderId)
+            .Where((redPackAudit, snapshot, order, special) => (snapshot.IndustryName == "安全隐患" && order.OrderTagCode!.Contains("DHZY")) || (order.CreationTime >=beginTime && order.CreationTime <= endTime && redPackAudit.ApprovedAmount == 20 && order.AcceptTypeCode != "30" && snapshot.IndustryName != "电气焊作业申报"))
+            .WhereIF(dto.Status == 0, (redPackAudit, snapshot, order, special) => special.Id == null)
+            .WhereIF(dto.Status == 1, (redPackAudit, snapshot, order, special) => special.Status == ERedPackAuditStatus.Agree)
+            .WhereIF(dto.Status == 2, (redPackAudit, snapshot, order, special) => special.Status == ERedPackAuditStatus.Refuse)
+            .OrderByDescending((redPackAudit, snapshot, order, special) => redPackAudit.CreationTime)
                         .Select((redPackAudit, snapshot,order) => new SnapshotOrderAuditItemsOutDto
                         {
                             Id = redPackAudit.Id,
@@ -526,6 +539,41 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         }
     }
 
+    /// <summary>
+    /// 添加补充发放信息(特殊红包)
+    /// </summary>
+    /// <param name="dto"></param>
+    /// <returns></returns>
+    public async Task UpdateRedPackSpecialRecordAsync(UpdateRedPackRecordInDto dto)
+    {
+        var record = await _redPackRecordRepository.Queryable()
+            .Where(m => m.RedPackAuditId == dto.RedPackAuditId)
+            .FirstAsync() ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        var audit = await _specialRedPackAuditRepository.GetAsync(dto.RedPackAuditId) ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+
+        dto.Adapt(audit);
+        await _specialRedPackAuditRepository.UpdateAsync(audit);
+
+        var entity = dto.Adapt<SupplementRecord>();
+        var industryName = await _orderSnapshotRepository.Queryable()
+            .Where(m => m.Id == record.OrderId)
+            .Select(m => new { m.IndustryName, m.IndustryId })
+            .FirstAsync();
+        entity.OrderId = record.OrderId;
+        entity.RedPackRecordId = record.Id;
+        entity.RedPackAuditId = audit.Id;
+        entity.No = record.No;
+        entity.IndustryName = industryName.IndustryName;
+        entity.IndustryId = industryName.IndustryId;
+        await _supplementRecordRepository.AddAsync(entity);
+
+        if (dto.IsSendSMS)
+        {
+            // TODO: 发送短信
+        }
+    }
+
+
     #region 红包发放记录
 
     /// <summary>
@@ -641,6 +689,75 @@ public class RedPackApplication : IRedPackApplication, IScopeDependency
         return query;
     }
 
+    public async Task AuditRedPackSpecialAuditAsync(UpdateRedPackSpecialAuditInDto dto)
+    {
+        var audit = await _redPackAuditRepository.GetAsync(dto.RedPackAuditId) ?? throw UserFriendlyException.SameMessage("审核记录不存在");
+        if (_specialRedPackAuditRepository.ExistByOrderId(audit.OrderId)) throw UserFriendlyException.SameMessage("已审核, 不可重复审核");
+        var specialAudit = audit.Adapt<SpecialRedPackAudit>();
+        if (dto.AuditTypeId.NotNullOrEmpty())
+        { 
+            var specialType = _systemDic.SnapshotRedPackSpecialType.FirstOrDefault(m => m.Id == dto.AuditTypeId);
+            if (specialType != null)
+            {
+                specialAudit.AuditType = specialType.DicDataName;
+                specialAudit.AuditTypeCode = specialType.DicDataValue;
+            }
+        }
+        specialAudit.Status = dto.Status;
+        specialAudit.ApprovedAmount = dto.ApprovedAmount;
+        specialAudit.AuditId = _sessionContext.UserId;
+        specialAudit.AuditName = _sessionContext.UserName;
+        specialAudit.AuditOrgId = _sessionContext.OrgId;
+        specialAudit.AuditOrgName = _sessionContext.OrgName;
+        await _specialRedPackAuditRepository.AddAsync(specialAudit);
+    }
+
+    public async Task<SnapshotOrderAuditSpecialDetailOutDto> GetRedPackSpecialAuditBaseDataAsync(string id)
+    {
+        var outDto = new SnapshotOrderAuditSpecialDetailOutDto();
+        var order = await _orderRepository.GetAsync(id) ?? throw new UserFriendlyException("工单不存在");
+        outDto.Order = order.Adapt<SnapshotOrderAuditOrderDetailOutDto>();
+        outDto.AuditType = _systemDic.SnapshotRedPackSpecialType;
+        outDto.AuditComBox = EnumExts.GetDescriptions<ERedPackAuditStatus>().Where(m => m.Key != 0).ToList();
+        var audit = await _redPackAuditRepository.GetAsync(m => m.OrderId == id);
+        outDto.AuditDetail = audit.Adapt<SnapshotOrderAuditSpecialAuditDetailOutDto>();
+        return outDto;
+    }
+
+    public async Task<GetRedPackRecordBaseDataOutDto> GetRedPackRecordBaseDataAsync(string orderId)
+    {
+        var snapshot = await _orderSnapshotRepository.Queryable()
+            .Where(m => m.Id == orderId)
+            .Select(m => new
+            {
+                m.Id,
+                m.AwardBankCardNo,
+                m.AwardOpenBank,
+                m.AwardName,
+                m.AwardAmount
+            })
+            .FirstAsync();
+        var outDto = new GetRedPackRecordBaseDataOutDto();
+        if (snapshot != null)
+        {
+            outDto.BankCardNo = snapshot.AwardBankCardNo;
+            outDto.OpenBank = snapshot.AwardOpenBank;
+            outDto.Name = snapshot.AwardName;
+            outDto.Amount = snapshot.AwardAmount;
+        }
+        var audit = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == orderId).FirstAsync() 
+            ?? throw new UserFriendlyException("审核记录不存在");
+        if (audit != null)
+        {
+            outDto.AuditType = audit.AuditType;
+            outDto.AuditTypeCode = audit.AuditTypeCode;
+            outDto.RedPackAuditId = audit.Id;
+        }
+        outDto.OrderId = orderId;
+        outDto.ReplenishType = _systemDic.SnapshotReplenishType;
+        return outDto;
+    }
+
 
     #endregion
 }

+ 24 - 0
src/Hotline.Repository.SqlSugar/Snapshot/SpecialRedPackAuditRepository.cs

@@ -0,0 +1,24 @@
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Snapshot;
+using Hotline.Snapshot.Interfaces;
+using MediatR;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Dependency;
+
+namespace Hotline.Repository.SqlSugar.Snapshot;
+public class SpecialRedPackAuditRepository : BaseRepository<SpecialRedPackAudit>, ISpecialRedPackAuditRepository, IScopeDependency
+{
+    public SpecialRedPackAuditRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
+    {
+    }
+
+    public bool ExistByOrderId(string orderId)
+    {
+        return Queryable().Where(m => m.OrderId == orderId).Any();
+    }
+}

+ 119 - 0
src/Hotline.Share/Dtos/Snapshot/OrderDto.cs

@@ -702,6 +702,58 @@ public class GetRedPackAuditSMSTemplateInDto
     public ESnapshotSMSStatus Status { get; set; }
 }
 
+public class SnapshotOrderAuditSpecialDetailOutDto
+{ 
+    /// <summary>
+    /// 工单信息
+    /// </summary>
+    public SnapshotOrderAuditOrderDetailOutDto Order { get; set; }
+
+    /// <summary>
+    /// 审核信息
+    /// </summary>
+    public SnapshotOrderAuditSpecialAuditDetailOutDto AuditDetail { get; set; }
+
+    /// <summary>
+    /// 审核状态
+    /// </summary>
+    public IEnumerable<KeyValuePair<int, string>> AuditComBox { get; set; }
+
+    /// <summary>
+    /// 审核类型
+    /// </summary>
+    public IEnumerable<SystemDicDataOutDto> AuditType { get; set; }
+}
+
+public class SnapshotOrderAuditSpecialAuditDetailOutDto
+{
+    /// <summary>
+    /// 审批人
+    /// </summary>
+    public string? AuditId { get; set; }
+
+    /// <summary>
+    /// 审批人
+    /// </summary>
+    public string? AuditName { get; set; }
+
+    /// <summary>
+    /// 审批部门
+    /// </summary>
+    public string? AuditOrgId { get; set; }
+
+    /// <summary>
+    /// 审批部门名称
+    /// </summary>
+    public string? AuditOrgName { get; set; }
+
+    /// <summary>
+    /// 审批意见
+    /// </summary>
+    public string? AuditRemark { get; set; }
+
+}
+
 public class SnapshotOrderAuditDetailOutDto
 {
     /// <summary>
@@ -860,6 +912,36 @@ public class UpdateRedPackGuiderAuditInDto
     public string Opinion { get; set; }
 }
 
+public class UpdateRedPackSpecialAuditInDto
+{
+    /// <summary>
+    /// 审核Id
+    /// </summary>
+    [Required]
+    public string RedPackAuditId { get; set; }
+
+    /// <summary>
+    /// 审核状态
+    /// </summary>
+    public ERedPackAuditStatus Status { get; set; }
+
+    /// <summary>
+    /// 审批类型
+    /// </summary>
+    public string? AuditTypeId { get; set; }
+
+    /// <summary>
+    /// 审核意见
+    /// </summary>
+    public string Opinion { get; set; }
+
+    /// <summary>
+    /// 审批金额
+    /// </summary>
+    public double? ApprovedAmount { get; set; }
+
+}
+
 public class UpdateRedPackAuditInDto
 {
     /// <summary>
@@ -889,6 +971,43 @@ public class UpdateRedPackAuditInDto
     public bool IsSendSms { get; set; }
 }
 
+public class GetRedPackRecordBaseDataOutDto
+{
+    /// <summary>
+    /// 金额
+    /// </summary>
+    public double? Amount { get; set; }
+
+    /// <summary>
+    /// 名字
+    /// </summary>
+    public string? Name { get; set; }
+
+    /// <summary>
+    /// 开户银行
+    /// </summary>
+    public string? OpenBank { get; set; }
+
+    /// <summary>
+    /// 银行卡号
+    /// </summary>
+    public string? BankCardNo { get; set; }
+
+    /// <summary>
+    /// 补充奖励类型
+    /// </summary>
+    public string? AuditType { get; set; }
+
+    /// <summary>
+    /// 补充奖励类型
+    /// </summary>
+    public string? AuditTypeCode { get; set; }
+    public string OrderId { get; set; }
+
+    public IReadOnlyCollection<SystemDicDataOutDto> ReplenishType { get; set; }
+
+    public string? RedPackAuditId { get; set; }
+}
 public class GetAuditBackBaseDataOutDto
 {
     /// <summary>

+ 5 - 0
src/Hotline/Caching/Interfaces/ISysDicDataCacheManager.cs

@@ -72,5 +72,10 @@ namespace Hotline.Caching.Interfaces
         IReadOnlyCollection<SystemDicDataOutDto> OrderTag { get; }
 
         IReadOnlyCollection<SystemDicDataOutDto> VisitSatisfaction { get; }
+
+        /// <summary>
+        /// 随手拍特殊红包审核类型
+        /// </summary>
+        IReadOnlyCollection<SystemDicDataOutDto> SnapshotRedPackSpecialType { get; }
     }
 }

+ 5 - 0
src/Hotline/Caching/Services/SysDicDataCacheManager.cs

@@ -137,6 +137,11 @@ namespace Hotline.Caching.Services
         /// </summary>
         public IReadOnlyCollection<SystemDicDataOutDto> VisitSatisfaction => GetOrAdd(SysDicTypeConsts.VisitSatisfaction);
 
+        /// <summary>
+        /// 随手拍特殊红包审核类型
+        /// </summary>
+        public IReadOnlyCollection<SystemDicDataOutDto> SnapshotRedPackSpecialType => GetOrAdd(SysDicTypeConsts.SnapshotRedPackSpecialType);
+
         public void RemoveSysDicDataCache(string code)
         {
             _cacheSysDicData.Remove(code);

+ 13 - 0
src/Hotline/SeedData/SystemDicDataSeedData.cs

@@ -17,6 +17,15 @@ public class SystemDicDataSeedData : ISeedData<SystemDicData>
 
     public IEnumerable<SystemDicData> GetData(string dicTypeCode)
     {
+        if (dicTypeCode == SysDicTypeConsts.SnapshotRedPackSpecialType)
+        {
+            return [
+                new() {  Id = "08dd4bf7-b7c6-471b-8ee5-deb5a1c4776a", DicDataValue = "dqh", DicDataName = "电气焊类", Sort = 1},
+                new() {  Id = "08dd4bf7-b7ab-4729-80b2-b2c5db5d221c", DicDataValue = "qp", DicDataName = "气瓶类", Sort = 2},
+                new() {  Id = "08dd4bf7-b352-4b52-8a96-78f73197c22e", DicDataValue = "dde", DicDataName = "电动车类", Sort = 3},
+                new() {  Id = "08dd4bf7-b349-48ea-8f54-fb8b29070fa3", DicDataValue = "xftd", DicDataName = "消防通道", Sort = 4},
+                ];
+        }
         if (dicTypeCode == SysDicTypeConsts.SnapshotOrderLabel)
         {
             return [
@@ -192,6 +201,10 @@ public class SystemDicDataSeedData : ISeedData<SystemDicData>
         {
             dicType = ["08dd1f12-0e81-47dc-82d7-559e36a68e0d", "补充奖励类型"];
         }
+        if (dicTypeCode == SysDicTypeConsts.SnapshotRedPackSpecialType)
+        {
+            dicType = ["08dd4bf7-b7cd-471b-8729-73b3ceaae8f5", "随手拍特殊红包审批类型"];
+        }
 
         return new SystemDicType
         {

+ 5 - 0
src/Hotline/Settings/SysDicTypeConsts.cs

@@ -306,4 +306,9 @@ public class SysDicTypeConsts
     /// 随手拍工单标签
     /// </summary>
     public static string SnapshotOrderLabel = "SnapshotOrderLabel";
+
+    /// <summary>
+    /// 随手拍特殊红包审核类型
+    /// </summary>
+    public static string SnapshotRedPackSpecialType = "SnapshotRedPackSpecialType";
 }

+ 12 - 0
src/Hotline/Snapshot/Interfaces/ISpecialRedPackAuditRepository.cs

@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+
+namespace Hotline.Snapshot.Interfaces;
+public interface ISpecialRedPackAuditRepository : IRepository<SpecialRedPackAudit>
+{
+    bool ExistByOrderId(string orderId);
+}

+ 137 - 0
src/Hotline/Snapshot/SpecialRedPackAudit.cs

@@ -0,0 +1,137 @@
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using XF.Domain.Repository;
+using Hotline.Orders;
+using Hotline.Share.Enums.Snapshot;
+
+namespace Hotline.Snapshot;
+
+/// <summary>
+/// 特殊红包审核
+/// 在特殊红包审核界面审核通过/不通过后生成数据
+/// </summary>
+[Description("特殊市民红包审核")]
+public class SpecialRedPackAudit : CreationSoftDeleteEntity
+{
+    /// <summary>
+    /// 关联工单编号
+    /// <inheritdoc cref="Order"/>表的Id字段
+    /// </summary>    
+    [SugarColumn(ColumnDescription = "关联工单编号")]
+    public string OrderId { get; set; }
+
+    /// <summary>
+    /// 领取手机号码
+    /// </summary>
+    [SugarColumn(ColumnDescription = "领取红包手机号码")]
+    public string? PhoneNumber { get; set; }
+
+    /// <summary>
+    /// 审核状态
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审核状态")]
+    public ERedPackAuditStatus Status { get; set; }
+
+    /// <summary>
+    /// 审批时间
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审批时间")]
+    public DateTime? AuditTime { get; set; }
+
+    /// <summary>
+    /// 配置金额
+    /// </summary>
+    [SugarColumn(ColumnDescription = "配置金额")]
+    public double ShouldAmount { get; set; }
+
+    /// <summary>
+    /// 审批金额
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审批金额")]
+    public double? ApprovedAmount { get; set; }
+
+    /// <summary>
+    /// 实发金额
+    /// </summary>
+    [SugarColumn(ColumnDescription = "实发金额")]
+    public double? AcutalAmount { get; set; }
+
+    /// <summary>
+    /// 市民奖励发放结果
+    /// </summary>
+    [SugarColumn(ColumnDescription = "市民奖励发放结果")]
+    public bool IsSend { get; set; }
+
+    /// <summary>
+    /// 市民奖励发放备注
+    /// </summary>
+    [SugarColumn(ColumnDescription = "市民奖励发放备注")]
+    public string? SendRemarks { get; set; }
+
+    /// <summary>
+    /// 操作人
+    /// </summary>
+    [SugarColumn(ColumnDescription = "操作人")]
+    public string? AuditId { get; set; }
+
+    /// <summary>
+    /// 操作人
+    /// </summary>
+    [SugarColumn(ColumnDescription = "操作人")]
+    public string? AuditName { get; set; }
+
+    /// <summary>
+    /// 审批部门
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审批部门")]
+    public string? AuditOrgId { get; set; }
+
+    /// <summary>
+    /// 审批部门名称
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审批部门名称")]
+    public string? AuditOrgName { get; set; }
+
+    /// <summary>
+    /// 审批意见
+    /// </summary>
+    [SugarColumn(ColumnDescription = "审批意见")]
+    public string? AuditRemark { get; set; }
+
+    public string? Remark { get; set; }
+
+    /// <summary>
+    /// 是否已发放
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否已发放")]
+    public bool? IsIssued { get; set; }
+
+    /// <summary>
+    /// 短信Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "短信Id")]
+    public string? SMSTemplateId { get; set; }
+
+    /// <summary>
+    /// 是否发送短信
+    /// </summary>
+    [SugarColumn(ColumnDescription = "是否发送短信")]
+    public bool? IsSendSMS { get; set; }
+
+    /// <summary>
+    /// 特殊红包审核,审批类型
+    /// </summary>
+    [SugarColumn(ColumnDescription = "特殊红包审核,审批类型")]
+    public string? AuditType { get; set; }
+
+    /// <summary>
+    /// 特殊红包审核,审批类型
+    /// </summary>
+    [SugarColumn(ColumnDescription = "特殊红包审核,审批类型")]
+    public string? AuditTypeCode { get; set; }
+}

+ 18 - 0
src/Hotline/Snapshot/SupplementRecord.cs

@@ -93,9 +93,27 @@ public class SupplementRecord : FullStateEntity
     [SugarColumn(ColumnDescription = "开户行")]
     public string? OpenBank { get; set; }
 
+    /// <summary>
+    /// 补充发放人姓名
+    /// </summary>
+    [SugarColumn(ColumnDescription = "补充发放人姓名")]
+    public string? Name { get; set; }
+
     /// <summary>
     /// 是否发送短信
     /// </summary>
     [SugarColumn(ColumnDescription = "是否发送短信")]
     public bool IsSendSMS { get; set; }
+
+    /// <summary>
+    /// 特殊红包审核,审批类型
+    /// </summary>
+    [SugarColumn(ColumnDescription = "特殊红包审核,审批类型")]
+    public string? AuditType { get; set; }
+
+    /// <summary>
+    /// 特殊红包审核,审批类型
+    /// </summary>
+    [SugarColumn(ColumnDescription = "特殊红包审核,审批类型")]
+    public string? AuditTypeCode { get; set; }
 }

+ 2 - 2
src/TianQue.Sdk/TiqnQueService.cs

@@ -98,8 +98,8 @@ public class TiqnQueService : IGuiderSystemService, IScopeDependency
             Message = result.Msg,
             Result = new GuiderSystemOutDto
             {
-                GuiderSystemId = result.Data.AppealNumber,
-                JsonData = result.Data.ToJson()
+                GuiderSystemId = result.Data?.AppealNumber,
+                JsonData = result.Data?.ToJson()
             }
         };
     }

+ 4 - 2
test/Hotline.Tests/Application/OrderSnapshotApplicationTest.cs

@@ -66,9 +66,11 @@ public class OrderSnapshotApplicationTest : TestBase
             .办理到网格员(SetZuoXi)
             .StepHandle(async order =>
             {
-                Thread.Sleep(30 * 1000);
+                Thread.Sleep(5 * 1000);
             }
-            ).GetCreateResult();
+            )
+            .办理到派单员(Set班长)
+            .GetCreateResult();
         order.Id.ShouldNotBeNull();
     }
 

+ 58 - 3
test/Hotline.Tests/Application/RedPackApplicationTest.cs

@@ -1,11 +1,15 @@
 using Hotline.Api.Controllers;
 using Hotline.Application.Snapshot;
+using Hotline.Caching.Interfaces;
 using Hotline.Identity.Accounts;
 using Hotline.Identity.Roles;
+using Hotline.Repository.SqlSugar.Snapshot;
 using Hotline.Settings;
+using Hotline.Share.Dtos;
 using Hotline.Share.Dtos.Snapshot;
 using Hotline.Share.Enums.Snapshot;
 using Hotline.Snapshot.Interfaces;
+using Hotline.Tests.Mock;
 using Hotline.Users;
 using Microsoft.AspNetCore.Http;
 using Microsoft.Extensions.DependencyInjection;
@@ -24,11 +28,19 @@ public class RedPackApplicationTest : TestBase
 {
     private readonly IRedPackApplication _redPackApplication;
     private readonly IRedPackRecordRepository _redPackRecordRepository;
+    private readonly OrderServiceMock _orderServiceMock;
+    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
+    private readonly IIndustryRepository _industryRepository;
+    private readonly ISpecialRedPackAuditRepository _specialRedPackAuditRepository;
 
-    public RedPackApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IRedPackApplication redPackApplication, IRedPackRecordRepository redPackRecordRepository, ITypedCache<SystemSetting> cacheSettingData) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
+    public RedPackApplicationTest(IAccountRepository accountRepository, IRepository<Role> roleRepository, UserController userController, IServiceScopeFactory scopeFactory, IRepository<User> userRepository, IHttpContextAccessor httpContextAccessor, IThirdIdentiyService thirdIdentiyService, IThirdAccountRepository thirdAccountRepository, IRedPackApplication redPackApplication, IRedPackRecordRepository redPackRecordRepository, ITypedCache<SystemSetting> cacheSettingData, OrderServiceMock orderServiceMock, ISystemDicDataCacheManager systemDicDataCacheManager, IIndustryRepository industryRepository, ISpecialRedPackAuditRepository specialRedPackAuditRepository) : base(accountRepository, roleRepository, userController, scopeFactory, userRepository, httpContextAccessor, thirdIdentiyService, thirdAccountRepository, cacheSettingData)
     {
         _redPackApplication = redPackApplication;
         _redPackRecordRepository = redPackRecordRepository;
+        _orderServiceMock = orderServiceMock;
+        _systemDicDataCacheManager = systemDicDataCacheManager;
+        _industryRepository = industryRepository;
+        _specialRedPackAuditRepository = specialRedPackAuditRepository;
     }
 
     /// <summary>
@@ -38,8 +50,51 @@ public class RedPackApplicationTest : TestBase
     [Fact]
     public async Task GetRedPackSpecialAuditItems_Test()
     {
-        var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).ToListAsync();
-        items.Count.ShouldNotBe(0);
+        var dhzy = _systemDicDataCacheManager.OrderTag.Where(m => m.DicDataName == "动火作业").FirstOrDefault();
+        dhzy.ShouldNotBeNull("SysDicTypeConsts.OrderTag 缺少动作火作业基础信息");
+        SetZuoXi();
+        SetSettingCache(SettingConstants.OvertimeBack, "0.00027778");
+        var industryItems = await _industryRepository.Queryable().Where(m => m.Name == "安全隐患").Select(d => new { d.Id, d.Name, }).ToListAsync();
+        var industry = industryItems.First();
+        var order = _orderServiceMock.CreateOrder(industryId: industry.Id, industryName: industry.Name, tags: [dhzy.Id])
+            .办理到网格员()
+            .StepHandle(async order => Thread.Sleep(5 * 1000))
+            .办理到派单员(Set班长)
+            .办理到一级部门(SetPaiDanYuan)
+            .办理到归档(Set一级部门)
+            .发布工单(SetZuoXi, _systemDicDataCacheManager.SnapshotOrderLabel.Where(m => m.DicDataValue == "bss").Select(m => new Kv(m.DicDataName, m.DicDataName)).ToList())
+            .部门审核市民红包(Set应急管理局)
+            .StepHandle(async order => 
+            {
+                var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).ToListAsync();
+                items.Where(m => m.No == order.No).Count().ShouldBe(1);
+                items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, -1)).ToListAsync();
+                items.Where(m => m.No == order.No).Count().ShouldBe(1);
+                items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 1)).ToListAsync();
+                items.Where(m => m.No == order.No).Count().ShouldBe(0, "审批同意不应该存在数据");
+                items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 2)).ToListAsync();
+                items.Where(m => m.No == order.No).Count().ShouldBe(0);
+            })
+            .部门审核特殊红包(Set应急管理局, 29)
+            .StepHandle(async order =>
+            {
+                var special = await _specialRedPackAuditRepository.Queryable().Where(m => m.OrderId == order.Id).FirstAsync();
+                special.ApprovedAmount.ShouldBe(29);
+                special.Status.ShouldBe(ERedPackAuditStatus.Agree);
+                special.AuditRemark.ShouldBe("红包审核通过");
+                var redPackAudit = await _redPackApplication.GetRedPackSpecialAuditBaseDataAsync(order.Id);
+                redPackAudit.AuditDetail.AuditId.ShouldNotBeNull();
+                redPackAudit.AuditDetail.AuditName.ShouldNotBeNull();
+                redPackAudit.AuditDetail.AuditOrgId.ShouldNotBeNull();
+                redPackAudit.AuditDetail.AuditOrgName.ShouldNotBeNull();
+                redPackAudit.AuditDetail.AuditRemark.ShouldNotBeNull("审核意见不能为空");
+                redPackAudit.AuditDetail.AuditRemark.ShouldBe("红包审核通过");
+
+                var items = await _redPackApplication.GetRedPackSpecialAuditItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 1)).ToListAsync();
+                items.Count.ShouldNotBe(0, $"工单No: {order.No}");
+            })
+            .GetCreateResult();
+
     }
 
     /// <summary>

+ 7 - 7
test/Hotline.Tests/Controller/DefaultSessionContext.cs

@@ -37,7 +37,7 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
     /// Id of current user or throw Exception for guest
     /// </summary>
     /// <exception cref="AuthenticationException"></exception>
-    public string RequiredUserId => _contextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
+    public string RequiredUserId => _contextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier);
     public string? UserName
     {
         get { return _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.UserDisplayName); }
@@ -46,7 +46,7 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
 
     public string? Phone
     {
-        get { return _contextAccessor.HttpContext.User.FindFirstValue(JwtClaimTypes.PhoneNumber); }
+        get { return _contextAccessor.HttpContext?.User.FindFirstValue(JwtClaimTypes.PhoneNumber); }
         init { }
     }
 
@@ -80,13 +80,13 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
 
     public string? OrgAreaCode
     {
-        get { return _contextAccessor.HttpContext.User.FindFirstValue(AppClaimTypes.DepartmentAreaCode); }
+        get { return _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentAreaCode); }
         init { }
     }
 
     public bool OrgIsCenter
     {
-        get { return _contextAccessor.HttpContext.User.FindBoolValue(AppClaimTypes.DepartmentIsCenter); }
+        get { return _contextAccessor.HttpContext?.User.FindBoolValue(AppClaimTypes.DepartmentIsCenter) ?? false; }
         init { }
     }
 
@@ -95,7 +95,7 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
     /// </summary>
     public string? OrgAreaName
     {
-        get { return _contextAccessor.HttpContext.User.FindFirstValue(AppClaimTypes.DepartmentAreaName); }
+        get { return _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.DepartmentAreaName); }
         init { }
     }
 
@@ -106,7 +106,7 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
     }
     public string? ClientId
     {
-        get { return _contextAccessor.HttpContext.User.FindFirstValue(JwtClaimTypes.ClientId); }
+        get { return _contextAccessor.HttpContext?.User.FindFirstValue(JwtClaimTypes.ClientId); }
         init { }
     }
 
@@ -115,7 +115,7 @@ public class DefaultSessionContext : ISessionContext, IScopeDependency
     /// </summary>
     public string? StaffNo
     {
-        get { return _contextAccessor.HttpContext.User.FindFirstValue(AppClaimTypes.StaffNo); }
+        get { return _contextAccessor.HttpContext?.User.FindFirstValue(AppClaimTypes.StaffNo); }
         init { }
     }
 }

+ 36 - 3
test/Hotline.Tests/Mock/OrderServiceMock.cs

@@ -26,6 +26,7 @@ using Hotline.Share.Dtos;
 using Hotline.FlowEngine.Notifications;
 using Hotline.Api.Controllers.Bi;
 using XF.Domain.Exceptions;
+using System;
 
 namespace Hotline.Tests.Mock;
 public class OrderServiceMock
@@ -41,8 +42,9 @@ public class OrderServiceMock
     public readonly ISessionContext _sessionContext;
     public readonly IOrderServiceStartWorkflow _orderServiceStartWorkflow;
     public readonly RedPackController _redPackController;
+    private readonly ISystemDicDataCacheManager _systemDicDataCacheManager;
 
-    public OrderServiceMock(OrderController orderController, IRepository<Order> orderRepository, IOrderVisitRepository orderVisitRepository, SnapshotController snapshotController, ISessionContext sessionContext, IOrderServiceStartWorkflow orderServiceStartWorkflow, ISystemSettingCacheManager systemSettingCacheManager, RedPackController redPackController)
+    public OrderServiceMock(OrderController orderController, IRepository<Order> orderRepository, IOrderVisitRepository orderVisitRepository, SnapshotController snapshotController, ISessionContext sessionContext, IOrderServiceStartWorkflow orderServiceStartWorkflow, ISystemSettingCacheManager systemSettingCacheManager, RedPackController redPackController, ISystemDicDataCacheManager systemDicDataCacheManager)
     {
         _orderController = orderController;
         _orderController.ControllerContext = new ControllerContext
@@ -62,9 +64,10 @@ public class OrderServiceMock
         _systemSettingCacheManager = systemSettingCacheManager;
         _redPackController = redPackController;
         _redPackController.ControllerContext = new ControllerContext
-        { 
+        {
             HttpContext = new DefaultHttpContext(),
         };
+        _systemDicDataCacheManager = systemDicDataCacheManager;
     }
 
     public IOrderServiceStartWorkflow CreateSnapshotOrder(Action action)
@@ -100,7 +103,7 @@ public class OrderServiceMock
         return _orderServiceStartWorkflow;
     }
 
-    public IOrderServiceStartWorkflow CreateOrder(string callId = "", string industryId = "", string industryName = "")
+    public IOrderServiceStartWorkflow CreateOrder(string callId = "", string industryId = "", string industryName = "", List<string> tags = null)
     {
         var json = "{\"sourceChannel\":\"因特网\",\"sourceChannelCode\":\"YTW\",\"transferPhone\":null,\"fromPhone\":null,\"acceptorName\":\"单元测试\",\"acceptorStaffNo\":\"\",\"fromName\":\"1233333333\",\"fromGender\":1,\"identityType\":1,\"licenceType\":null,\"licenceTypeCode\":null,\"licenceNo\":null,\"ageRange\":null,\"ageRangeCode\":null,\"contact\":\"12333333333\",\"isSecret\":false,\"acceptSms\":false,\"no\":null,\"title\":\"\",\"hotspotId\":\"1912\",\"eventCategoryId\":null,\"incidentTime\":null,\"incidentPurpose\":null,\"areaCode\":\"519800\",\"city\":\"省内\",\"street\":null,\"isRepeat\":\"false\",\"pushType\":null,\"pushTypeCode\":null,\"content\":\"单元测试内容\",\"duplicateIds\":[],\"duplicateTitle\":null,\"callAddress\":null,\"repeatableEventDetails\":[],\"orderExtension\":null,\"transpond\":false,\"isEnforcementOrder\":false,\"focusOnEventsArr\":[],\"focusOnEvents\":null,\"isFormalistWorkOrder\":false,\"isSensitiveWorkOrders\":false,\"isUrgent\":false,\"isThreePartyConference\":false,\"is24HoursComplete\":false,\"company\":null,\"orderPushTypes\":[],\"acceptType\":\"咨询\",\"acceptTypeCode\":\"10\",\"files\":[],\"hotspotSpliceName\":\"互联互通-转接乐山市12345\",\"hotspotName\":\"转接乐山市12345\",\"hotspotCode\":\"1912\",\"hotspotExternal\":\"19\",\"county\":\"\",\"town\":\"\"}";
         AddOrderDto = json.FromJson<AddOrderDto>();
@@ -113,11 +116,20 @@ public class OrderServiceMock
         AddOrderDto.IndustryId = industryId;
         AddOrderDto.IndustryName = industryName;
         AddOrderDto.Title = "单元测试" + DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
+        if (tags.NotNullOrEmpty())
+            AddOrderDto.Tags = tags;
         CreateOrderOutDto = _orderController.Add(AddOrderDto).GetAwaiter().GetResult().ToJson().FromJson<CreateOrderOutDto>();
         _orderServiceStartWorkflow.orderServiceMock = this;
         return _orderServiceStartWorkflow;
     }
 
+    public OrderServiceMock UpdateOrder()
+    {
+        UpdateOrderDto order = _orderController.Get(CreateOrderOutDto.Id).GetAwaiter().GetResult();
+        _orderController.Update(order).GetAwaiter().GetResult();
+        return this;
+    }
+
     public CreateOrderOutDto GetCreateResult()
     {
         return CreateOrderOutDto;
@@ -473,4 +485,25 @@ public class OrderServiceMock
         return this;
     }
 
+    public OrderServiceMock 部门审核特殊红包(Action action, double? approvedAmount = 0)
+    {
+        action?.Invoke();
+        var baseData = _redPackController.GetRedPackSpecialItems(new SnapshotOrderAuditItemsInDto(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 0)).GetAwaiter().GetResult();
+        var item = baseData.Items.FirstOrDefault(m => m.No == CreateOrderOutDto.No);
+        var basedata = _systemDicDataCacheManager.SnapshotRedPackSpecialType.First();
+        if (item == null)
+            throw UserFriendlyException.SameMessage("获取特殊审核红包信息错误, 不存在被测试的对象.");
+        var inDto = new UpdateRedPackSpecialAuditInDto
+        {
+            AuditTypeId = basedata.Id,
+            ApprovedAmount = approvedAmount,
+            RedPackAuditId = item.RedPackAuditId,
+            Status = ERedPackAuditStatus.Agree,
+            Opinion = "红包审核通过",
+        };
+
+        _redPackController.UpdateRedPackSpecialAuditAsync(inDto).GetAwaiter().GetResult();
+        return this;
+
+    }
 }