using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.GenerateAutoNumber; using static GB5Shared.GB5Constant.Constant; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using GB5Shared.Validation; using Microsoft.Extensions.Logging; using PERMBLL.Interfaces; using PERMDAL.DTOs; using PERMDAL.Interfaces; using System.Text.Json; namespace PERMBLL.Implementations; public class KRABLL : IKRABLL { private readonly IKRADAL _dal; private readonly IValidation _validation; private readonly AutoNumber _autoNumber; private readonly KeyInvalidate _keyInvalidate; private readonly EventLogPublish _eventLog; private readonly ILogger _logger; public KRABLL( IKRADAL dal, IValidation validation, AutoNumber autoNumber, KeyInvalidate keyInvalidate, EventLogPublish eventLog, ILogger logger) { _dal = dal; _validation = validation; _autoNumber = autoNumber; _keyInvalidate = keyInvalidate; _eventLog = eventLog; _logger = logger; } public async Task GetKRAAsync(int kraId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-kra", new { kraId }); var dto = await _dal.GetKRAAsync(kraId, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(dto); } catch (Exception ex) { GB5Trace.MarkFailed("get-kra-failed", ex); _logger.LogError(ex, "GetKRA failed for KRAId {KRAId}", kraId); throw; } } public async Task GetKRAListAsync( short? status, short? nature, int page, int pageSize, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-kra-list", new { status, nature, page }); var list = await _dal.GetKRAListAsync(status, nature, page, pageSize, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } catch (Exception ex) { GB5Trace.MarkFailed("get-kra-list-failed", ex); _logger.LogError(ex, "GetKRAList failed"); throw; } } public async Task GetKRASelectListAsync(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) { try { var list = await _dal.GetKRASelectListAsync(criteriaDTO, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } catch (Exception ex) { GB5Trace.MarkFailed("get-kra-selectlist-failed", ex); _logger.LogError(ex, "GetKRASelectList failed"); throw; } } public async Task SaveKRAAsync(KRADTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-kra", new { dto.KRAId }); await _validation.NotEmpty(dto.KRAName, nameof(dto.KRAName)).ConfigureAwait(false); bool duplicate = await _dal.KRANameExistsAsync(dto.KRAName, dto.KRAId, login, ct).ConfigureAwait(false); if (duplicate) return $"KRA name '{dto.KRAName}' already exists."; bool isNew = dto.KRAId == 0; GB5Trace.Step("save-kra", new { dto.KRAId, isNew }); int rows; if (isNew) { dto.TenantId = login.ClientId; dto.Status = 1; rows = await _dal.SaveKRAAsync(dto, login, ct).ConfigureAwait(false); } else { rows = await _dal.UpdateKRAAsync(dto, login, ct).ConfigureAwait(false); } if (rows == 0) return "No rows affected — KRA not saved."; GB5Trace.Step("event-publish", new { EventTypeId = isNew ? EventTypeConstant.SAVEPERMKRAEVENTTYPEID : EventTypeConstant.UPDATEPERMKRAEVENTTYPEID }); await _eventLog.PublishEventLogAsync( isNew ? "KRA Created" : "KRA Updated", dto, isNew ? EventTypeConstant.SAVEPERMKRAEVENTTYPEID : EventTypeConstant.UPDATEPERMKRAEVENTTYPEID, dto.KRAId, login, ct: ct).ConfigureAwait(false); var saveCacheKey = new CacheKeyGeneration().KeyGeneration(dto.KRAId, EntityConstant.OBJECTPERMKRA, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(saveCacheKey).ConfigureAwait(false); return isNew ? SuccessResponse.SaveSuccess : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-kra-failed", ex); _logger.LogError(ex, "SaveKRA failed for KRAName {KRAName}", dto.KRAName); throw; } } public async Task DeleteKRAAsync(int kraId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("delete-kra", new { kraId }); int rows = await _dal.DeleteKRAAsync(kraId, login, ct).ConfigureAwait(false); if (rows == 0) return "KRA not found or already deleted."; GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.DELETEPERMKRAEVENTTYPEID }); await _eventLog.PublishEventLogAsync( "KRA Deleted", new { KRAId = kraId }, EventTypeConstant.DELETEPERMKRAEVENTTYPEID, kraId, login, ct: ct).ConfigureAwait(false); var deleteCacheKey = new CacheKeyGeneration().KeyGeneration(kraId, EntityConstant.OBJECTPERMKRA, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(deleteCacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Trace.MarkFailed("delete-kra-failed", ex); _logger.LogError(ex, "DeleteKRA failed for KRAId {KRAId}", kraId); throw; } } }