using FrameworkDAL.DTO.EIPConversation; using FrameworkDAL.Query.EIPConversation.EIPFlowAdmin; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using static GB5Shared.GB5Constant.Constant; namespace FrameworkDAL.CustomCode.EIPConversation.EIPFlowAdmin { public class EIPFlowAdminDAL : IEIPFlowAdminDAL { private readonly IQueryExecutor _qe; private readonly AutoNumber _autoNumber; private readonly ILogger _logger; public EIPFlowAdminDAL(IQueryExecutor qe, AutoNumber autoNumber, ILogger logger) { _qe = qe ?? throw new ArgumentNullException(nameof(qe)); _autoNumber = autoNumber ?? throw new ArgumentNullException(nameof(autoNumber)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public async Task> GetFlowListAsync( byte? flowStatus, string? search, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); try { _logger.LogInformation( "DAL | GetFlowList | Tenant={TenantId} | FlowStatus={FlowStatus} | Search={Search}", login.ClientId, flowStatus, search); var result = await _qe.QueryAsync( login, EIPFlowAdminQB.GET_FLOW_LIST, new { TenantId = login.ClientId, FlowStatus = flowStatus, Search = search }, cancellationToken: ct).ConfigureAwait(false); return result ?? []; } catch (OperationCanceledException) { _logger.LogWarning("DAL | GetFlowList | Cancelled | Tenant={TenantId}", login.ClientId); throw; } catch (Exception ex) { _logger.LogError(ex, "DAL | GetFlowList | Error | Tenant={TenantId}", login.ClientId); throw; } } public async Task GetFlowAsync( int flowDefinitionId, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); try { _logger.LogInformation( "DAL | GetFlow | Tenant={TenantId} | FlowDefinitionId={FlowDefinitionId}", login.ClientId, flowDefinitionId); return await _qe.QuerySingleAsync( login, EIPFlowAdminQB.GET_FLOW, new { FlowDefinitionId = flowDefinitionId, TenantId = login.ClientId }, cancellationToken: ct).ConfigureAwait(false); } catch (OperationCanceledException) { _logger.LogWarning("DAL | GetFlow | Cancelled | FlowDefinitionId={Id}", flowDefinitionId); throw; } catch (Exception ex) { _logger.LogError(ex, "DAL | GetFlow | Error | FlowDefinitionId={Id}", flowDefinitionId); throw; } } public async Task InsertFlowAsync( EIPFlowAdminDTO dto, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); try { _logger.LogInformation( "DAL | InsertFlow | Tenant={TenantId} | FlowCode={FlowCode}", login.ClientId, dto.FlowCode); // FLOWDEFINITIONID is a plain INT PK (not IDENTITY) — must be generated here. var auto = await _autoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.EIPFLOWDEFINITION, login) .ConfigureAwait(false); var newId = auto.StartNumber; await _qe.ExecuteAsync( login, EIPFlowAdminQB.INSERT_FLOW, new { FlowDefinitionId = newId, TenantId = login.ClientId, dto.FlowCode, dto.FlowVersion, dto.FlowStatus, dto.JsonDefinition, dto.Version, CreatedById = login.UserId }, cancellationToken: ct).ConfigureAwait(false); _logger.LogInformation( "DAL | InsertFlow | Completed | NewId={NewId}", newId); return newId; } catch (OperationCanceledException) { _logger.LogWarning("DAL | InsertFlow | Cancelled | FlowCode={FlowCode}", dto.FlowCode); throw; } catch (Exception ex) { _logger.LogError(ex, "DAL | InsertFlow | Error | FlowCode={FlowCode}", dto.FlowCode); throw; } } public async Task UpdateFlowAsync( EIPFlowAdminDTO dto, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); try { _logger.LogInformation( "DAL | UpdateFlow | Tenant={TenantId} | FlowDefinitionId={FlowDefinitionId}", login.ClientId, dto.FlowDefinitionId); await _qe.ExecuteAsync( login, EIPFlowAdminQB.UPDATE_FLOW, new { dto.FlowDefinitionId, TenantId = login.ClientId, dto.FlowVersion, dto.FlowStatus, dto.JsonDefinition, dto.Version, ModifiedById = login.UserId }, cancellationToken: ct).ConfigureAwait(false); } catch (OperationCanceledException) { _logger.LogWarning( "DAL | UpdateFlow | Cancelled | FlowDefinitionId={Id}", dto.FlowDefinitionId); throw; } catch (Exception ex) { _logger.LogError( ex, "DAL | UpdateFlow | Error | FlowDefinitionId={Id}", dto.FlowDefinitionId); throw; } } public async Task DeleteFlowAsync( int flowDefinitionId, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); try { _logger.LogInformation( "DAL | DeleteFlow | Tenant={TenantId} | FlowDefinitionId={FlowDefinitionId}", login.ClientId, flowDefinitionId); await _qe.ExecuteAsync( login, EIPFlowAdminQB.DELETE_FLOW, new { FlowDefinitionId = flowDefinitionId, TenantId = login.ClientId, ModifiedById = login.UserId }, cancellationToken: ct).ConfigureAwait(false); } catch (OperationCanceledException) { _logger.LogWarning("DAL | DeleteFlow | Cancelled | FlowDefinitionId={Id}", flowDefinitionId); throw; } catch (Exception ex) { _logger.LogError(ex, "DAL | DeleteFlow | Error | FlowDefinitionId={Id}", flowDefinitionId); throw; } } public async Task FlowCodeExistsAsync( string flowCode, int tenantId, int excludeFlowDefinitionId, LoginDTO login, CancellationToken ct = default) { ct.ThrowIfCancellationRequested(); var count = await _qe.ExecuteScalarAsync( login, EIPFlowAdminQB.EXISTS_FLOWCODE, new { FlowCode = flowCode, TenantId = tenantId, FlowDefinitionId = excludeFlowDefinitionId }, cancellationToken: ct).ConfigureAwait(false); return count == 1; } } }