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.MarketingCampaign; using MarketingDAL.DTO.MarketingCampaign; using Microsoft.Extensions.Logging; using static GB5Shared.GB5Constant.Constant; namespace MarketingBLL.MarketingCampaign; /// /// BLL for MMKTCAMPAIGN — the external, customer-facing Marketing Campaign (distinct from CMS's /// internal employee-learning "Campaign" — see MarketingCampaignDTO's class doc). Also the target /// of Lead.LeadCampaignId (TLEAD.CAMPAIGNID), wired via FK in this session's migration. /// public class MarketingCampaignBLL : IMarketingCampaignBLL { private readonly IMarketingCampaignDAL _MarketingCampaignDAL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; private readonly ILogger _Logger; public MarketingCampaignBLL( IMarketingCampaignDAL marketingCampaignDAL, AutoNumber autoNumber, IValidation validation, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService, ILogger logger) { _MarketingCampaignDAL = marketingCampaignDAL; _AutoNumber = autoNumber; _Validation = validation; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; _Logger = logger; } public async Task GetMarketingCampaign(int campaignId, LoginDTO loginDTO, CancellationToken ct) { try { return await _MarketingCampaignDAL.GetMarketingCampaign(campaignId, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-marketingcampaign-failed", ex); _Logger.LogError(ex, "GetMarketingCampaign failed for CampaignId {CampaignId}", campaignId); throw; } } public async Task SaveMarketingCampaign(MarketingCampaignDTO marketingCampaignDTO, LoginDTO loginDTO, CancellationToken ct) { if (marketingCampaignDTO == null) throw new ArgumentNullException(nameof(marketingCampaignDTO)); AutoNumberDTO? autoNumberDTO = null; try { GB5Trace.Step("validate-marketingcampaign", new { marketingCampaignDTO.CampaignId }); await _Validation.NotEmpty(marketingCampaignDTO.CampaignCode, nameof(marketingCampaignDTO.CampaignCode)); await _Validation.NotEmpty(marketingCampaignDTO.CampaignName, nameof(marketingCampaignDTO.CampaignName)); await _Validation.Range((byte)1, (byte)5, marketingCampaignDTO.CampaignType, nameof(marketingCampaignDTO.CampaignType)); if (marketingCampaignDTO.SegmentId == 0) marketingCampaignDTO.SegmentId = -1; marketingCampaignDTO.ModifiedById = loginDTO.UserId; marketingCampaignDTO.ModifiedOn = DateTime.UtcNow; bool isNew = marketingCampaignDTO.CampaignId == 0; if (isNew) { autoNumberDTO = await _AutoNumber.GetNumberAsync(1, "MKTCAMPAIGN", loginDTO).ConfigureAwait(false); marketingCampaignDTO.CampaignId = autoNumberDTO.StartNumber; marketingCampaignDTO.CreatedById = loginDTO.UserId; marketingCampaignDTO.CreatedOn = DateTime.UtcNow; } GB5Trace.Step("save-marketingcampaign", new { marketingCampaignDTO.CampaignId, isNew }); await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTMARKETINGCAMPAIGN, isNew ? EventTypeConstant.SAVEMARKETINGCAMPAIGNEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGCAMPAIGNEVENTTYPEID, marketingCampaignDTO, loginDTO, async tx => { _ = isNew ? await _MarketingCampaignDAL.SaveMarketingCampaign(marketingCampaignDTO, loginDTO, tx, ct).ConfigureAwait(false) : await _MarketingCampaignDAL.UpdateMarketingCampaign(marketingCampaignDTO, loginDTO, tx, ct).ConfigureAwait(false); return marketingCampaignDTO.CampaignId; }, null, -1, -1, null, isNew).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = isNew ? EventTypeConstant.SAVEMARKETINGCAMPAIGNEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGCAMPAIGNEVENTTYPEID }); var cacheKey = new CacheKeyGeneration().KeyGeneration( marketingCampaignDTO.CampaignId, EntityConstant.OBJECTMARKETINGCAMPAIGN, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("MarketingCampaign {CampaignId} {Action} by user {UserId}", marketingCampaignDTO.CampaignId, isNew ? "saved" : "updated", loginDTO.UserId); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {marketingCampaignDTO.CampaignId}" : $"{SuccessResponse.UpdateSuccessMessage} {marketingCampaignDTO.CampaignId}"; } catch (ValidationException vex) { GB5Trace.MarkFailed("save-marketingcampaign-failed", vex); if (autoNumberDTO != null && marketingCampaignDTO.CampaignId > 0) await _AutoNumber.RollbackAutoNumber("MKTCAMPAIGN", marketingCampaignDTO.CampaignId, loginDTO).ConfigureAwait(false); throw new Exception(vex.Message); } catch (Exception ex) { GB5Trace.MarkFailed("save-marketingcampaign-failed", ex); _Logger.LogError(ex, "SaveMarketingCampaign failed for CampaignId {CampaignId}", marketingCampaignDTO.CampaignId); if (autoNumberDTO != null && marketingCampaignDTO.CampaignId > 0) await _AutoNumber.RollbackAutoNumber("MKTCAMPAIGN", marketingCampaignDTO.CampaignId, loginDTO).ConfigureAwait(false); throw; } } public async Task GetSelectListMarketingCampaign(CriteriaDTO criteriaDTO, LoginDTO loginDTO, CancellationToken ct) { try { return await _MarketingCampaignDAL.GetSelectListMarketingCampaign(criteriaDTO, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-selectlist-marketingcampaign-failed", ex); _Logger.LogError(ex, "GetSelectListMarketingCampaign failed"); throw; } } public async Task DeleteMarketingCampaign(int campaignId, LoginDTO loginDTO, CancellationToken ct) { try { GB5Trace.Step("delete-marketingcampaign", new { campaignId }); var result = await _MarketingCampaignDAL.DeleteMarketingCampaign(campaignId, loginDTO, ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( campaignId, EntityConstant.OBJECTMARKETINGCAMPAIGN, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("MarketingCampaign {CampaignId} deleted by user {UserId}", campaignId, loginDTO.UserId); return result; } catch (Exception ex) { GB5Trace.MarkFailed("delete-marketingcampaign-failed", ex); _Logger.LogError(ex, "DeleteMarketingCampaign failed for CampaignId {CampaignId}", campaignId); throw; } } }