组织机构
框架内置了组织机构功能,支持从第三方系统同步数据,为业务系统提供统一的组织数据。 本文主要对同步服务和扩展方式作出说明。
默认实现
默认情况下,框架仅从 HRM 系统接收以下信息:
| 名称 | 说明 |
|---|---|
| orgId | 编号 |
| orgName | 名称 |
| orgCode | 编码 |
| orgTypeName | 类型 |
| globalOrder | 全局排序号 |
| operateTime | 修改时间 |
| inUse | 状态 |
| parentOrgId | 父编号 |
| orgFullPath | 名称全路径 |
提示
从 3.3.2 起,同步服务内部会生成组织编码全路径信息,存储为 FullCode。
提示
现在更推荐使用 /api/org/sync-raw 从网关接收上游接口原始数据。
OrgSyncService<T, D> v3.3.2+
OrgSyncService 是接收组织数据的默认服务实现类,它实现了 IOrgSyncService<D> 接口, 其中 T 为实体类型,D 为 DTO 类型。
数据关键处理逻辑和方法如下表所示。
| 步骤 | 方法 | 说明 |
|---|---|---|
| 1 | SyncData | 将接收到的数据分页传入下一步处理,每页50条 |
| 2 | DoSyncPagedData | 核心方法,根据传入的数据获取本地数据,然后依次决定要更新还是新增 |
| 3.1 | SearchOldToMap | 获取本地数据并转换为字典,以便后续判断数据是否存在 |
| 3.2 | DataNotChange | 当本地数据存在时,判断数据是否变化,未变化则跳过,不作更新。数据变化的判断依据为更新时间 |
| 3.3 | OnDataUpdate | 准备要更新的数据,填充属性 |
| 3.4 | OnDataAdd | 准备要新增的数据,填充属性 |
| 3.5 | OnDataSaving | 入库前的自定义操作 |
| 3.6 | OnDataSaved | 入库后的自定义操作 |
| 1.2 | OnSyncFinish | 数据处理完毕的自定义操作。上游数据有可能分多次传递,因此此方法也可能会产生多次调用。 |
提示
以上所有方法都支持重写,方便开发者扩展自己的处理逻辑。
字段扩展
如果默认的字段不能满足业务需要,可以进行字段扩展。关键在于定义新的实体类和 DTO 类。
实体
创建实体类,继承 Organization。
csharp
/// <summary>
/// 自定义组织
/// </summary>
[Table("Organization")]
public class MyOrganization : Organization
{
/// <summary>
/// 示例字段
/// </summary>
public string Foo { get; set; }
}DTO
创建 DTO 类以接收新增字段,继承 OrganizationSyncRawDto。
csharp
/// <summary>
/// 自定义组织dto
/// </summary>
public class MyOrgSyncRawDto: OrganizationSyncRawDto
{
/// <summary>
/// 示例字段
/// </summary>
public string Foo { get; set; }
}DAL
与数据库交互需要与实体类对应的 DAL,因此也需要重新定义。
csharp
/// <summary>
/// 自定义组织dal
/// </summary>
public interface IMyOrgDal : IBaseDal<MyOrganization>
{
}
/// <summary>
/// 自定义组织dal
/// </summary>
[Repository]
public class MyOrganizationDal : BaseDal<MyOrganization>, IMyOrgDal
{
}Controller
声明新的接口,使用新 DTO 类接收数据。
csharp
/// <summary>
/// 自定义组织同步
/// </summary>
/// <param name="syncService"></param>
[ApiController]
public class MyOrgController(IOrgSyncService<MyOrgSyncRawDto> syncService)
{
/// <summary>
/// 同步
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("/api/my-org/sync-raw")]
[Authorize(AuthenticationSchemes = "api,sign")]
public Result SyncRaw(List<MyOrgSyncRawDto> input)
{
syncService.SyncData(input);
return Result.Success();
}
}服务注册
最后,需要注册新的 DAL 服务和 Service 服务。
csharp
// [startup.cs]
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
// 注册自定义服务
services.AddScoped<IOrgSyncService<MyOrgSyncRawDto>, OrgSyncService<MyOrganization,MyOrgSyncRawDto>>();
// 后续内容省略
}业务逻辑扩展
如果需要更多个性化的操作,可以声明新服务类并重写方法。
服务实现
csharp
public class MyOrgSyncService(IUserDal userDal, IDataDictionaryService dict): OrgSyncService<MyOrganization, MyOrgSyncRawDto>(userDal)
{
Dictionary<string,string> config;
/// <inheritdoc/>
public override void SyncData(List<MyOrgSyncRawDto> dto)
{
config = dict.ListByName("dict_foo", false).ToDictionary(t=> t.DicKey, t=> t.DicValue);
base.SyncData(dto);
}
/// <inheritdoc/>
protected override MyOrganization OnDataAdd(MyOrgSyncRawDto org)
{
// 框架逻辑
MyOrganization entity = base.OnDataAdd(org);
// 自定义
entity.Foo = config.TryGetValue(org.Foo, out string val) ? val : "";
return entity;
}
/// <inheritdoc/>
protected override MyOrganization OnDataUpdate(MyOrgSyncRawDto org, MyOrganization old)
{
// 框架逻辑
MyOrganization entity = base.OnDataUpdate(org, old);
// 自定义
entity.Foo = config.TryGetValue(org.Foo, out string val) ? val : "";
return entity;
}
}在以上示例中,重写了几个关键方法。在 SyncData 方法中加载了字典数据,用于后续数据处理。 在 OnDataAdd、OnDataUpdate方法中使用字典数据填充自定义字段。
注意
上例中使用了构造函数注入依赖。也可以使用 [Autowired] 方式注入,但要注意在控制器中同样需要使用 [Autowired] 注入服务。
服务注册
csharp
// [startup.cs]
public override void ConfigureServices(IServiceCollection services)
{
base.ConfigureServices(services);
// 注册自定义服务
services.AddScoped<IOrgSyncService<MyOrgSyncRawDto>, MyOrgSyncService<MyOrganization, MyOrgSyncRawDto>>();
// 后续内容省略
}