using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EntityHandler; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using PIEDAL.CustomCode.Variant; using PIEDAL.DTO.Variant; using static GB5Shared.GB5Constant.Constant; namespace PIEBLL.Variant; public class PIEVariantBLL : IPIEVariantBLL { private readonly IPIEVariantDAL _PIEVariantDAL; private readonly IQueryExecutor _QueryExecutor; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; public PIEVariantBLL( IPIEVariantDAL pieVariantDAL, IQueryExecutor queryExecutor, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService) { _PIEVariantDAL = pieVariantDAL; _QueryExecutor = queryExecutor; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; } // ── Reads ───────────────────────────────────────────────────────────────── public async Task GetPIEVariantAsync( Guid variantId, LoginDTO login, CancellationToken ct) { var variant = await _PIEVariantDAL.GetPIEVariantAsync(variantId, login, ct).ConfigureAwait(false); if (variant is null) return null; var implications = await _PIEVariantDAL.GetPIEVariantImplicationsAsync(variantId, login, ct).ConfigureAwait(false); variant.Implications = implications.ToList(); return variant; } public async Task> GetPIEVariantsByModuleAsync( Guid moduleId, LoginDTO login, CancellationToken ct) => await _PIEVariantDAL.GetPIEVariantsByModuleAsync(moduleId, login, ct).ConfigureAwait(false); // ── Saves ───────────────────────────────────────────────────────────────── public async Task SavePIEVariantAsync( PIEVariantDTO dto, LoginDTO login, CancellationToken ct) { if (dto is null) throw new ArgumentNullException(nameof(dto)); // Validate: implication types 1–5 require RefId foreach (var imp in dto.Implications) { if (imp.ImplicationType is >= 1 and <= 5 && imp.RefId is null) throw new ArgumentException( $"Implication type {imp.ImplicationType} requires a RefId."); } bool isNew = dto.VariantId == Guid.Empty; if (isNew) dto.VariantId = Guid.NewGuid(); var Trans = await _QueryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTPIEVARIANT, isNew ? EventTypeConstant.SAVEPIEVARIANTEVENTTYPEID : EventTypeConstant.UPDATEPIEVARIANTEVENTTYPEID, dto, login, async tx => { if (isNew) await _PIEVariantDAL.SavePIEVariantAsync(dto, login, tx, ct).ConfigureAwait(false); else await _PIEVariantDAL.UpdatePIEVariantAsync(dto, login, tx, ct).ConfigureAwait(false); // Replace implications (delete-reinsert) await _PIEVariantDAL.DeleteVariantImplicationsAsync(dto.VariantId, login, tx, ct).ConfigureAwait(false); foreach (var imp in dto.Implications) { imp.ImplicationId = imp.ImplicationId == Guid.Empty ? Guid.NewGuid() : imp.ImplicationId; imp.VariantId = dto.VariantId; imp.TenantId = dto.TenantId; await _PIEVariantDAL.InsertVariantImplicationAsync(imp, login, tx, ct).ConfigureAwait(false); } return 0; // PIEVariant uses a Guid PK — no int object ID to report back }, null, BIZTRANSACTIONCLASSCONSTANT.PIEVARIANT, BizTransactionConstant.PIEVARIANT, Trans).ConfigureAwait(false); await _QueryExecutor.CommitAsync(Trans).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( dto.VariantId, EntityConstant.OBJECTPIEVARIANT, CacheKeyLevel.CLIENT_LEVEL, login); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return isNew ? SuccessResponse.SaveSuccess : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Shared.Telemetry.GB5Trace.MarkFailed("save-pie-variant-failed", ex); await _QueryExecutor.RollbackAsync(Trans).ConfigureAwait(false); throw; } } public async Task DeletePIEVariantAsync( Guid variantId, LoginDTO login, CancellationToken ct) { var Trans = await _QueryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTPIEVARIANT, EventTypeConstant.DELETEPIEVARIANTEVENTTYPEID, new PIEVariantDTO { VariantId = variantId }, login, async tx => { await _PIEVariantDAL.SoftDeletePIEVariantAsync(variantId, login, tx, ct).ConfigureAwait(false); return 0; }, null, BIZTRANSACTIONCLASSCONSTANT.PIEVARIANT, BizTransactionConstant.PIEVARIANT, Trans).ConfigureAwait(false); await _QueryExecutor.CommitAsync(Trans).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( variantId, EntityConstant.OBJECTPIEVARIANT, CacheKeyLevel.CLIENT_LEVEL, login); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Shared.Telemetry.GB5Trace.MarkFailed("delete-pie-variant-failed", ex); await _QueryExecutor.RollbackAsync(Trans).ConfigureAwait(false); throw; } } }