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;
}
}
}