using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; 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 MeasureBLL : IMeasureBLL { private readonly IMeasureDAL _dal; private readonly IValidation _validation; private readonly KeyInvalidate _keyInvalidate; private readonly EventLogPublish _eventLog; private readonly ILogger _logger; public MeasureBLL( IMeasureDAL dal, IValidation validation, KeyInvalidate keyInvalidate, EventLogPublish eventLog, ILogger logger) { _dal = dal; _validation = validation; _keyInvalidate = keyInvalidate; _eventLog = eventLog; _logger = logger; } public async Task GetMeasureAsync(int measureId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-measure", new { measureId }); var dto = await _dal.GetMeasureAsync(measureId, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(dto); } catch (Exception ex) { GB5Trace.MarkFailed("get-measure-failed", ex); _logger.LogError(ex, "GetMeasure failed for MeasureId {MeasureId}", measureId); throw; } } public async Task GetMeasureListAsync( short? status, short? measureType, int page, int pageSize, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("get-measure-list", new { status, measureType, page }); var list = await _dal.GetMeasureListAsync(status, measureType, page, pageSize, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } catch (Exception ex) { GB5Trace.MarkFailed("get-measure-list-failed", ex); _logger.LogError(ex, "GetMeasureList failed"); throw; } } public async Task GetMeasureSelectListAsync(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) { try { var list = await _dal.GetMeasureSelectListAsync(criteriaDTO, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } catch (Exception ex) { GB5Trace.MarkFailed("get-measure-selectlist-failed", ex); _logger.LogError(ex, "GetMeasureSelectList failed"); throw; } } public async Task SaveMeasureAsync(MeasureDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-measure", new { dto.MeasureId }); await _validation.NotEmpty(dto.MeasureName, nameof(dto.MeasureName)).ConfigureAwait(false); bool duplicate = await _dal.MeasureNameExistsAsync(dto.MeasureName, dto.MeasureId, login, ct).ConfigureAwait(false); if (duplicate) return $"Measure name '{dto.MeasureName}' already exists."; bool isNew = dto.MeasureId == 0; GB5Trace.Step("save-measure", new { dto.MeasureId, isNew }); int rows; if (isNew) { dto.TenantId = login.ClientId; dto.Status = 1; rows = await _dal.SaveMeasureAsync(dto, login, ct).ConfigureAwait(false); } else { rows = await _dal.UpdateMeasureAsync(dto, login, ct).ConfigureAwait(false); } if (rows == 0) return "No rows affected — Measure not saved."; GB5Trace.Step("event-publish", new { EventTypeId = isNew ? EventTypeConstant.SAVEPERMMEASUREEVENTTYPEID : EventTypeConstant.UPDATEPERMMEASUREEVENTTYPEID }); await _eventLog.PublishEventLogAsync( isNew ? "Measure Created" : "Measure Updated", dto, isNew ? EventTypeConstant.SAVEPERMMEASUREEVENTTYPEID : EventTypeConstant.UPDATEPERMMEASUREEVENTTYPEID, dto.MeasureId, login, ct: ct).ConfigureAwait(false); var saveCacheKey = new CacheKeyGeneration().KeyGeneration(dto.MeasureId, EntityConstant.OBJECTPERMMEASURE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(saveCacheKey).ConfigureAwait(false); return isNew ? SuccessResponse.SaveSuccess : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-measure-failed", ex); _logger.LogError(ex, "SaveMeasure failed for MeasureName {MeasureName}", dto.MeasureName); throw; } } public async Task DeleteMeasureAsync(int measureId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("delete-measure", new { measureId }); int rows = await _dal.DeleteMeasureAsync(measureId, login, ct).ConfigureAwait(false); if (rows == 0) return "Measure not found or already deleted."; GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.DELETEPERMMEASUREEVENTTYPEID }); await _eventLog.PublishEventLogAsync( "Measure Deleted", new { MeasureId = measureId }, EventTypeConstant.DELETEPERMMEASUREEVENTTYPEID, measureId, login, ct: ct).ConfigureAwait(false); var deleteCacheKey = new CacheKeyGeneration().KeyGeneration(measureId, EntityConstant.OBJECTPERMMEASURE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(deleteCacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Trace.MarkFailed("delete-measure-failed", ex); _logger.LogError(ex, "DeleteMeasure failed for MeasureId {MeasureId}", measureId); throw; } } }