using System.ComponentModel.DataAnnotations; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.EntityHandler; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using GB5Shared.Validation; using MarketingDAL.CustomCode.Segment; using MarketingDAL.DTO.Segment; using Microsoft.Extensions.Logging; using static GB5Shared.GB5Constant.Constant; namespace MarketingBLL.Segment; public class SegmentBLL : ISegmentBLL { private readonly ISegmentDAL _SegmentDAL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; private readonly ILogger _Logger; public SegmentBLL( ISegmentDAL segmentDAL, AutoNumber autoNumber, IValidation validation, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService, ILogger logger) { _SegmentDAL = segmentDAL; _AutoNumber = autoNumber; _Validation = validation; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; _Logger = logger; } public async Task GetSegment(int segmentId, LoginDTO loginDTO, CancellationToken ct) { try { return await _SegmentDAL.GetSegment(segmentId, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-segment-failed", ex); _Logger.LogError(ex, "GetSegment failed for SegmentId {SegmentId}", segmentId); throw; } } public async Task SaveSegment(SegmentDTO segmentDTO, LoginDTO loginDTO, CancellationToken ct) { if (segmentDTO == null) throw new ArgumentNullException(nameof(segmentDTO)); AutoNumberDTO? autoNumberDTO = null; try { GB5Trace.Step("validate-segment", new { segmentDTO.SegmentId }); await _Validation.NotEmpty(segmentDTO.SegmentCode, nameof(segmentDTO.SegmentCode)); await _Validation.NotEmpty(segmentDTO.SegmentName, nameof(segmentDTO.SegmentName)); await _Validation.Range(1, 3, segmentDTO.SegmentType, nameof(segmentDTO.SegmentType)); segmentDTO.ModifiedById = loginDTO.UserId; segmentDTO.ModifiedOn = DateTime.UtcNow; bool isNew = segmentDTO.SegmentId == 0; if (isNew) { autoNumberDTO = await _AutoNumber.GetNumberAsync(1, "SEGMENT", loginDTO).ConfigureAwait(false); segmentDTO.SegmentId = autoNumberDTO.StartNumber; segmentDTO.CreatedById = loginDTO.UserId; segmentDTO.CreatedOn = DateTime.UtcNow; } GB5Trace.Step("save-segment", new { segmentDTO.SegmentId, isNew }); await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTMARKETINGSEGMENT, isNew ? EventTypeConstant.SAVEMARKETINGSEGMENTEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGSEGMENTEVENTTYPEID, segmentDTO, loginDTO, async tx => { _ = isNew ? await _SegmentDAL.SaveSegment(segmentDTO, loginDTO, tx, ct).ConfigureAwait(false) : await _SegmentDAL.UpdateSegment(segmentDTO, loginDTO, tx, ct).ConfigureAwait(false); return segmentDTO.SegmentId; }, null, -1, -1, null, isNew).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = isNew ? EventTypeConstant.SAVEMARKETINGSEGMENTEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGSEGMENTEVENTTYPEID }); var cacheKey = new CacheKeyGeneration().KeyGeneration( segmentDTO.SegmentId, EntityConstant.OBJECTMARKETINGSEGMENT, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("Segment {SegmentId} {Action} by user {UserId}", segmentDTO.SegmentId, isNew ? "saved" : "updated", loginDTO.UserId); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {segmentDTO.SegmentId}" : $"{SuccessResponse.UpdateSuccessMessage} {segmentDTO.SegmentId}"; } catch (ValidationException vex) { GB5Trace.MarkFailed("save-segment-failed", vex); if (autoNumberDTO != null && segmentDTO.SegmentId > 0) await _AutoNumber.RollbackAutoNumber("SEGMENT", segmentDTO.SegmentId, loginDTO).ConfigureAwait(false); throw new Exception(vex.Message); } catch (Exception ex) { GB5Trace.MarkFailed("save-segment-failed", ex); _Logger.LogError(ex, "SaveSegment failed for SegmentId {SegmentId}", segmentDTO.SegmentId); if (autoNumberDTO != null && segmentDTO.SegmentId > 0) await _AutoNumber.RollbackAutoNumber("SEGMENT", segmentDTO.SegmentId, loginDTO).ConfigureAwait(false); throw; } } public async Task GetSelectListSegment(CriteriaDTO criteriaDTO, LoginDTO loginDTO, CancellationToken ct) { try { return await _SegmentDAL.GetSelectListSegment(criteriaDTO, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-selectlist-segment-failed", ex); _Logger.LogError(ex, "GetSelectListSegment failed"); throw; } } public async Task DeleteSegment(int segmentId, LoginDTO loginDTO, CancellationToken ct) { try { GB5Trace.Step("delete-segment", new { segmentId }); var result = await _SegmentDAL.DeleteSegment(segmentId, loginDTO, ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( segmentId, EntityConstant.OBJECTMARKETINGSEGMENT, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("Segment {SegmentId} deleted by user {UserId}", segmentId, loginDTO.UserId); return result; } catch (Exception ex) { GB5Trace.MarkFailed("delete-segment-failed", ex); _Logger.LogError(ex, "DeleteSegment failed for SegmentId {SegmentId}", segmentId); throw; } } }