feat(workflow): 添加业务编号生成器并集成到工作流引擎
- 新增 BusinessNoGenerator 类用于生成 YYYYMM + 4位序列号格式的业务编号 - 添加 BusinessNoSequence 实体类用于存储业务编号序列记录 - 在 WorkflowEngineApp 中注入 BusinessNoGenerator 依赖 - 修改工作流发起逻辑,移除手动传入业务编号改为自动生成 - 集成业务编号生成功能在流程实例创建过程中自动分配编号 - 添加批量生成业务编号的功能支持 - 重构工作流相关文件目录结构到 workflow 命名空间下main
parent
84f06b463f
commit
d46ee3a002
|
|
@ -0,0 +1,123 @@
|
||||||
|
using DocumentFormat.OpenXml.Wordprocessing;
|
||||||
|
using SqlSugar;
|
||||||
|
|
||||||
|
namespace OpenAuth.App.workflow;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 业务编号生成器
|
||||||
|
/// 格式:YYYYMM + 4位序列号 (如:2024120001)
|
||||||
|
/// </summary>
|
||||||
|
public class BusinessNoGenerator
|
||||||
|
{
|
||||||
|
private readonly ISqlSugarClient _sqlSugar;
|
||||||
|
private static readonly object _lockObject = new object();
|
||||||
|
|
||||||
|
public BusinessNoGenerator(ISqlSugarClient sqlSugar)
|
||||||
|
{
|
||||||
|
_sqlSugar = sqlSugar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成业务编号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix">业务前缀(可选)</param>
|
||||||
|
/// <returns>业务编号</returns>
|
||||||
|
public string GenerateBusinessNo(string prefix = "")
|
||||||
|
{
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
var currentDate = DateTime.Now;
|
||||||
|
var yearMonth = currentDate.ToString("yyyyMM");
|
||||||
|
|
||||||
|
// 查询当天最大序列号
|
||||||
|
var todayPrefix = $"{prefix}{yearMonth}";
|
||||||
|
var maxSequence = _sqlSugar.Queryable<BusinessNoSequence>()
|
||||||
|
.Where(s => s.DatePrefix == todayPrefix)
|
||||||
|
.OrderByDescending(s => s.SequenceNumber)
|
||||||
|
.Select(s => s.SequenceNumber)
|
||||||
|
.First();
|
||||||
|
// 计算新的序列号
|
||||||
|
var newSequence = maxSequence + 1;
|
||||||
|
|
||||||
|
// 更新序列号记录
|
||||||
|
var sequenceRecord = new BusinessNoSequence
|
||||||
|
{
|
||||||
|
DatePrefix = todayPrefix,
|
||||||
|
SequenceNumber = newSequence,
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果记录不存在则插入,否则更新
|
||||||
|
var existingRecord = _sqlSugar.Queryable<BusinessNoSequence>()
|
||||||
|
.Where(s => s.DatePrefix == todayPrefix)
|
||||||
|
.First();
|
||||||
|
|
||||||
|
if (existingRecord == null)
|
||||||
|
{
|
||||||
|
_sqlSugar.Insertable(sequenceRecord).ExecuteCommand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sqlSugar.Updateable<BusinessNoSequence>()
|
||||||
|
.SetColumns(s => new BusinessNoSequence
|
||||||
|
{
|
||||||
|
SequenceNumber = newSequence,
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
})
|
||||||
|
.Where(s => s.DatePrefix == todayPrefix)
|
||||||
|
.ExecuteCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化返回业务编号
|
||||||
|
return $"{todayPrefix}{newSequence:D4}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量生成业务编号
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">生成数量</param>
|
||||||
|
/// <param name="prefix">业务前缀</param>
|
||||||
|
/// <returns>业务编号列表</returns>
|
||||||
|
public List<string> GenerateBatchBusinessNo(int count, string prefix = "")
|
||||||
|
{
|
||||||
|
var businessNos = new List<string>();
|
||||||
|
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
businessNos.Add(GenerateBusinessNo(prefix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return businessNos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 业务编号序列记录表
|
||||||
|
/// </summary>
|
||||||
|
[SugarTable("zy_business_no_sequence")]
|
||||||
|
public class BusinessNoSequence
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 日期前缀 (YYYYMM格式)
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "dateprefix")]
|
||||||
|
public string DatePrefix { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前序列号
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "sequencenumber")]
|
||||||
|
|
||||||
|
public int SequenceNumber { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最后更新时间
|
||||||
|
/// </summary>
|
||||||
|
[SugarColumn(ColumnName = "lastupdatetime")]
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -7,29 +7,7 @@ using OpenAuth.Repository.Domain.workflow;
|
||||||
using OpenAuth.WebApi.Controllers.ServerController;
|
using OpenAuth.WebApi.Controllers.ServerController;
|
||||||
using SqlSugar;
|
using SqlSugar;
|
||||||
|
|
||||||
namespace workflow;
|
namespace OpenAuth.App.workflow;
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using OpenAuth.App.BaseApp.Base;
|
|
||||||
using OpenAuth.App.Interface;
|
|
||||||
using OpenAuth.Repository;
|
|
||||||
using OpenAuth.Repository.Domain;
|
|
||||||
using SqlSugar;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using OpenAuth.App.BaseApp.Base;
|
|
||||||
using OpenAuth.App.Interface;
|
|
||||||
using OpenAuth.Repository;
|
|
||||||
using OpenAuth.Repository.Domain;
|
|
||||||
using OpenAuth.Repository.Domain.workflow;
|
|
||||||
using SqlSugar;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 完整工作流引擎(适配:区县→执法监督科→5个审核科会签→汇总归档/退回)
|
/// 完整工作流引擎(适配:区县→执法监督科→5个审核科会签→汇总归档/退回)
|
||||||
|
|
@ -39,6 +17,8 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
|
||||||
{
|
{
|
||||||
private readonly ISqlSugarClient _sqlSugar;
|
private readonly ISqlSugarClient _sqlSugar;
|
||||||
|
|
||||||
|
private readonly BusinessNoGenerator _businessNoGenerator;
|
||||||
|
|
||||||
// 配置:5个审核科角色ID(需与sys_role表对应,自行修改为实际值)
|
// 配置:5个审核科角色ID(需与sys_role表对应,自行修改为实际值)
|
||||||
private readonly List<long> _auditDeptRoleIds = new()
|
private readonly List<long> _auditDeptRoleIds = new()
|
||||||
{
|
{
|
||||||
|
|
@ -53,9 +33,10 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
|
||||||
private const long _supervisionDeptRoleId = 6;
|
private const long _supervisionDeptRoleId = 6;
|
||||||
|
|
||||||
public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<SysCategoryType> repository,
|
public WorkflowEngineApp(ISugarUnitOfWork<SugarDbContext> unitWork, ISimpleClient<SysCategoryType> repository,
|
||||||
IAuth auth) : base(unitWork, repository, auth)
|
IAuth auth,BusinessNoGenerator businessNoGenerator) : base(unitWork, repository, auth)
|
||||||
{
|
{
|
||||||
_sqlSugar = Repository.AsSugarClient();
|
_sqlSugar = Repository.AsSugarClient();
|
||||||
|
_businessNoGenerator = businessNoGenerator;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 一、核心业务:流程发起/处理
|
#region 一、核心业务:流程发起/处理
|
||||||
|
|
@ -70,8 +51,8 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
|
||||||
public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
|
public long InitiateFlow(long userId, string userName, InitiateFlowRequestDto requestDto)
|
||||||
{
|
{
|
||||||
// 参数校验
|
// 参数校验
|
||||||
if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
|
/*if (string.IsNullOrEmpty(requestDto.FlowCode) || string.IsNullOrEmpty(requestDto.BusinessNo))
|
||||||
throw new Exception("流程编码和业务编号不能为空");
|
throw new Exception("流程编码和业务编号不能为空");*/
|
||||||
if (userId <= 0 || string.IsNullOrEmpty(userName))
|
if (userId <= 0 || string.IsNullOrEmpty(userName))
|
||||||
throw new Exception("发起人ID和姓名不能为空");
|
throw new Exception("发起人ID和姓名不能为空");
|
||||||
var instanceId = 0L;
|
var instanceId = 0L;
|
||||||
|
|
@ -93,7 +74,11 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
|
||||||
.First();
|
.First();
|
||||||
if (startNode == null)
|
if (startNode == null)
|
||||||
throw new Exception("流程开始节点【区县提交】不存在,请配置节点");
|
throw new Exception("流程开始节点【区县提交】不存在,请配置节点");
|
||||||
|
var currentDate = DateTime.Now;
|
||||||
|
var yearMonth = currentDate.ToString("yyyyMM");
|
||||||
|
var prefix = "wfjszl";
|
||||||
|
var businessNo = _businessNoGenerator.GenerateBusinessNo(prefix);
|
||||||
|
requestDto.BusinessNo = businessNo;
|
||||||
// 步骤3:插入流程实例,返回自增主键
|
// 步骤3:插入流程实例,返回自增主键
|
||||||
var flowInstance = new ZyFlowInstance
|
var flowInstance = new ZyFlowInstance
|
||||||
{
|
{
|
||||||
|
|
@ -107,7 +92,6 @@ public class WorkflowEngineApp : SqlSugarBaseApp<SysCategoryType, SugarDbContext
|
||||||
CreateTime = DateTime.Now
|
CreateTime = DateTime.Now
|
||||||
};
|
};
|
||||||
instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
|
instanceId = _sqlSugar.Insertable(flowInstance).ExecuteReturnIdentity();
|
||||||
|
|
||||||
// 步骤4:插入开始节点工作项(直接标记为已完成)
|
// 步骤4:插入开始节点工作项(直接标记为已完成)
|
||||||
var startWorkitem = new ZyFlowWorkitem
|
var startWorkitem = new ZyFlowWorkitem
|
||||||
{
|
{
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using OpenAuth.App.Interface;
|
using OpenAuth.App.Interface;
|
||||||
|
using OpenAuth.App.workflow;
|
||||||
using OpenAuth.Repository.Domain;
|
using OpenAuth.Repository.Domain;
|
||||||
using OpenAuth.Repository.Domain.workflow;
|
using OpenAuth.Repository.Domain.workflow;
|
||||||
using workflow;
|
|
||||||
|
|
||||||
namespace OpenAuth.WebApi.Controllers.ServerController;
|
namespace OpenAuth.WebApi.Controllers.ServerController;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue