using Microsoft.Extensions.Logging; namespace Admin.NET.Plugin.AiDOP.DataPlatform; /// 租户标准对象来源登记。页面入口见 F-5「业务对象来源」。 [ApiDescriptionSettings(Order = 325, Description = "租户标准对象来源登记")] [Route("api/DataPlatform")] [NonUnify] public class MdpTenantStdSourceService : IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; private readonly UserManager _userManager; private readonly MdpNeutralSourceCleanup _cleanup; private readonly ILogger _logger; public MdpTenantStdSourceService( ISqlSugarClient db, UserManager userManager, MdpNeutralSourceCleanup cleanup, ILoggerFactory loggerFactory) { _db = db; _userManager = userManager; _cleanup = cleanup; _logger = loggerFactory.CreateLogger(nameof(MdpTenantStdSourceService)); } [DisplayName("标准对象目录")] [HttpGet("std-objects")] public object Catalog() => MdpStdObjectCatalog.All.Select(d => new { code = d.Code, module = d.Module, isS0 = d.IsS0, targetTable = d.Tables.FirstOrDefault() }); [DisplayName("标准对象来源登记")] [HttpGet("tenant-std-sources")] public async Task List([FromQuery] long? tenantId) { var tenant = tenantId ?? _userManager.TenantId; if (!_userManager.SuperAdmin && !_userManager.SysAdmin && tenant != _userManager.TenantId) throw Oops.Oh("不能查看其他租户的来源登记"); return await _db.Ado.SqlQueryAsync( """ SELECT tenant_id AS TenantId, std_object AS StdObject, source_system AS SourceSystem, source_scope AS SourceScope, remark AS Remark, update_time AS UpdateTime FROM mdp_tenant_std_source WHERE tenant_id=@tenant ORDER BY std_object """, new { tenant }); } [DisplayName("修改标准对象来源登记")] [HttpPut("tenant-std-sources")] public async Task Upsert([FromBody] MdpTenantStdSourceInput input) { if (input.TenantId <= 0 || string.IsNullOrWhiteSpace(input.StdObject) || string.IsNullOrWhiteSpace(input.SourceSystem)) throw Oops.Oh("tenantId、stdObject、sourceSystem 必填"); if (!_userManager.SuperAdmin && !_userManager.SysAdmin && input.TenantId != _userManager.TenantId) throw Oops.Oh("不能修改其他租户的来源登记"); if (MdpStdObjectCatalog.Find(input.StdObject) == null) throw Oops.Oh($"未知标准对象 {input.StdObject}"); var old = await _db.Ado.SqlQueryAsync( "SELECT source_system FROM mdp_tenant_std_source WHERE tenant_id=@tenant AND std_object=@obj LIMIT 1", new { tenant = input.TenantId, obj = input.StdObject.Trim() }); var previous = old.FirstOrDefault(); await _db.Ado.ExecuteCommandAsync( """ INSERT INTO mdp_tenant_std_source (tenant_id, std_object, source_system, source_scope, remark) VALUES (@tenant, @obj, @src, @scope, @remark) ON DUPLICATE KEY UPDATE source_system=VALUES(source_system), source_scope=VALUES(source_scope), remark=VALUES(remark) """, new { tenant = input.TenantId, obj = input.StdObject.Trim(), src = input.SourceSystem.Trim(), scope = input.SourceScope?.Trim() ?? "", remark = input.Remark }); await _db.Ado.ExecuteCommandAsync( """ INSERT INTO mdp_tenant_std_source_log (tenant_id, std_object, old_source_system, new_source_system, changed_by) VALUES (@tenant, @obj, @old, @src, @who) """, new { tenant = input.TenantId, obj = input.StdObject.Trim(), old = previous, src = input.SourceSystem.Trim(), who = string.IsNullOrWhiteSpace(_userManager.Account) ? "api" : _userManager.Account }); var removed = 0; if (!string.Equals(previous, input.SourceSystem.Trim(), StringComparison.OrdinalIgnoreCase)) removed = await _cleanup.PurgeObjectAsync(input.TenantId, input.StdObject.Trim()); _logger.LogInformation( "来源登记 tenant={Tenant} object={Object} {Old} -> {New} purged={Purged}", input.TenantId, input.StdObject, previous, input.SourceSystem, removed); return new { tenantId = input.TenantId, stdObject = input.StdObject, purged = removed }; } } public sealed class MdpTenantStdSourceInput { public long TenantId { get; set; } public string StdObject { get; set; } = ""; public string SourceSystem { get; set; } = ""; public string? SourceScope { get; set; } public string? Remark { get; set; } }