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.Collateral; using MarketingDAL.DTO.Collateral; using Microsoft.Extensions.Logging; using static GB5Shared.GB5Constant.Constant; namespace MarketingBLL.Collateral; public class CollateralBLL : ICollateralBLL { private readonly ICollateralDAL _CollateralDAL; private readonly AutoNumber _AutoNumber; private readonly IValidation _Validation; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; private readonly ILogger _Logger; public CollateralBLL( ICollateralDAL collateralDAL, AutoNumber autoNumber, IValidation validation, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService, ILogger logger) { _CollateralDAL = collateralDAL; _AutoNumber = autoNumber; _Validation = validation; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; _Logger = logger; } public async Task GetCollateral(int collateralId, LoginDTO loginDTO, CancellationToken ct) { try { return await _CollateralDAL.GetCollateral(collateralId, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-collateral-failed", ex); _Logger.LogError(ex, "GetCollateral failed for CollateralId {CollateralId}", collateralId); throw; } } public async Task SaveCollateral(CollateralDTO collateralDTO, LoginDTO loginDTO, CancellationToken ct) { if (collateralDTO == null) throw new ArgumentNullException(nameof(collateralDTO)); AutoNumberDTO? autoNumberDTO = null; try { GB5Trace.Step("validate-collateral", new { collateralDTO.CollateralId }); await _Validation.NotEmpty(collateralDTO.CollateralCode, nameof(collateralDTO.CollateralCode)); await _Validation.NotEmpty(collateralDTO.CollateralTitle, nameof(collateralDTO.CollateralTitle)); if (collateralDTO.LinkedProductId == 0) collateralDTO.LinkedProductId = -1; if (collateralDTO.LinkedPersonaId == 0) collateralDTO.LinkedPersonaId = -1; if (collateralDTO.SourceDocumentId == 0) collateralDTO.SourceDocumentId = -1; collateralDTO.ModifiedById = loginDTO.UserId; collateralDTO.ModifiedOn = DateTime.UtcNow; bool isNew = collateralDTO.CollateralId == 0; if (isNew) { autoNumberDTO = await _AutoNumber.GetNumberAsync(1, "COLLATERAL", loginDTO).ConfigureAwait(false); collateralDTO.CollateralId = autoNumberDTO.StartNumber; collateralDTO.CreatedById = loginDTO.UserId; collateralDTO.CreatedOn = DateTime.UtcNow; } GB5Trace.Step("save-collateral", new { collateralDTO.CollateralId, isNew }); await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTMARKETINGCOLLATERAL, isNew ? EventTypeConstant.SAVEMARKETINGCOLLATERALEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGCOLLATERALEVENTTYPEID, collateralDTO, loginDTO, async tx => { _ = isNew ? await _CollateralDAL.SaveCollateral(collateralDTO, loginDTO, tx, ct).ConfigureAwait(false) : await _CollateralDAL.UpdateCollateral(collateralDTO, loginDTO, tx, ct).ConfigureAwait(false); return collateralDTO.CollateralId; }, null, -1, -1, null, isNew).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = isNew ? EventTypeConstant.SAVEMARKETINGCOLLATERALEVENTTYPEID : EventTypeConstant.UPDATEMARKETINGCOLLATERALEVENTTYPEID }); var cacheKey = new CacheKeyGeneration().KeyGeneration( collateralDTO.CollateralId, EntityConstant.OBJECTMARKETINGCOLLATERAL, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("Collateral {CollateralId} {Action} by user {UserId}", collateralDTO.CollateralId, isNew ? "saved" : "updated", loginDTO.UserId); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {collateralDTO.CollateralId}" : $"{SuccessResponse.UpdateSuccessMessage} {collateralDTO.CollateralId}"; } catch (ValidationException vex) { GB5Trace.MarkFailed("save-collateral-failed", vex); if (autoNumberDTO != null && collateralDTO.CollateralId > 0) await _AutoNumber.RollbackAutoNumber("COLLATERAL", collateralDTO.CollateralId, loginDTO).ConfigureAwait(false); throw new Exception(vex.Message); } catch (Exception ex) { GB5Trace.MarkFailed("save-collateral-failed", ex); _Logger.LogError(ex, "SaveCollateral failed for CollateralId {CollateralId}", collateralDTO.CollateralId); if (autoNumberDTO != null && collateralDTO.CollateralId > 0) await _AutoNumber.RollbackAutoNumber("COLLATERAL", collateralDTO.CollateralId, loginDTO).ConfigureAwait(false); throw; } } public async Task GetSelectListCollateral(CriteriaDTO criteriaDTO, LoginDTO loginDTO, CancellationToken ct) { try { return await _CollateralDAL.GetSelectListCollateral(criteriaDTO, loginDTO, ct).ConfigureAwait(false); } catch (Exception ex) { GB5Trace.MarkFailed("get-selectlist-collateral-failed", ex); _Logger.LogError(ex, "GetSelectListCollateral failed"); throw; } } public async Task DeleteCollateral(int collateralId, LoginDTO loginDTO, CancellationToken ct) { try { GB5Trace.Step("delete-collateral", new { collateralId }); var result = await _CollateralDAL.DeleteCollateral(collateralId, loginDTO, ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( collateralId, EntityConstant.OBJECTMARKETINGCOLLATERAL, CacheKeyLevel.CLIENT_LEVEL, loginDTO); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); _Logger.LogInformation("Collateral {CollateralId} deleted by user {UserId}", collateralId, loginDTO.UserId); return result; } catch (Exception ex) { GB5Trace.MarkFailed("delete-collateral-failed", ex); _Logger.LogError(ex, "DeleteCollateral failed for CollateralId {CollateralId}", collateralId); throw; } } }