using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using IDMSDAL.DTOs; using IDMSDAL.Interfaces; using IDMSBLL.Interfaces; using static GB5Shared.GB5Constant.Constant; using GB5Shared.EntityHandler; namespace IDMSBLL.Implementations; public class ClientContactBLL : IClientContactBLL { private readonly IClientContactDAL _ClientContactDAL; private readonly AutoNumber _AutoNumber; private readonly IQueryExecutor _QueryExecutor; private readonly KeyInvalidate _KeyInvalidate; private readonly BaseEntityAppService _BaseEntityAppService; public ClientContactBLL( IClientContactDAL clientContactDAL, AutoNumber autoNumber, IQueryExecutor queryExecutor, KeyInvalidate keyInvalidate, BaseEntityAppService baseEntityAppService) { _ClientContactDAL = clientContactDAL; _AutoNumber = autoNumber; _QueryExecutor = queryExecutor; _KeyInvalidate = keyInvalidate; _BaseEntityAppService = baseEntityAppService; } // ── Reads ───────────────────────────────────────────────────────────────── public async Task GetClientContactAsync( int contactId, LoginDTO login, CancellationToken ct) { return await _ClientContactDAL.GetContactAsync(contactId, login, ct) .ConfigureAwait(false); } public async Task> GetClientContactsByEngagementAsync( int engagementId, LoginDTO login, CancellationToken ct) { return await _ClientContactDAL.GetContactsByEngagementAsync(engagementId, login, ct) .ConfigureAwait(false); } // ── Writes ──────────────────────────────────────────────────────────────── public async Task SaveClientContactAsync( ClientContactDTO dto, LoginDTO login, CancellationToken ct) { if (dto is null) throw new ArgumentNullException(nameof(dto)); if (string.IsNullOrWhiteSpace(dto.FullName)) throw new ArgumentException("FullName is required.", nameof(dto)); if (string.IsNullOrWhiteSpace(dto.Email)) throw new ArgumentException("Email is required.", nameof(dto)); bool isNew = dto.ContactId == 0; if (isNew) { var auto = await _AutoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.IDMSCLIENTCONTACT, login) .ConfigureAwait(false); dto.ContactId = auto.StartNumber; } var Trans = await _QueryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTIDMSCLIENTCONTACT, EventTypeConstant.SAVEIDMSCLIENTCONTACTEVENTTYPEID, dto, login, async tx => { if (isNew) await _ClientContactDAL.SaveContactAsync(dto, login, tx, ct).ConfigureAwait(false); else await _ClientContactDAL.UpdateContactAsync(dto, login, tx, ct).ConfigureAwait(false); return dto.ContactId; }, new Dictionary { { "EngagementId", dto.EngagementId } }, BIZTRANSACTIONCLASSCONSTANT.IDMSCLIENTCONTACT, BizTransactionConstant.IDMSCLIENTCONTACT, Trans).ConfigureAwait(false); await _QueryExecutor.CommitAsync(Trans).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( dto.EngagementId, EntityConstant.OBJECTIDMSCLIENTCONTACT, CacheKeyLevel.CLIENT_LEVEL, login); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return isNew ? SuccessResponse.SaveSuccess : SuccessResponse.UpdateSuccess; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans).ConfigureAwait(false); throw; } } public async Task DeactivateClientContactAsync( int contactId, LoginDTO login, CancellationToken ct) { var contact = await _ClientContactDAL.GetContactAsync(contactId, login, ct) .ConfigureAwait(false) ?? throw new InvalidOperationException($"Client contact {contactId} not found."); if (contact.Status == 2) throw new InvalidOperationException("Contact is already deactivated."); var Trans = await _QueryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _BaseEntityAppService.ExecuteSaveAsync( EntityConstant.OBJECTIDMSCLIENTCONTACT, EventTypeConstant.SAVEIDMSCLIENTCONTACTEVENTTYPEID, contact, login, async tx => { await _ClientContactDAL.DeactivateContactAsync(contactId, login, tx, ct) .ConfigureAwait(false); return contactId; }, new Dictionary { { "EngagementId", contact.EngagementId } }, BIZTRANSACTIONCLASSCONSTANT.IDMSCLIENTCONTACT, BizTransactionConstant.IDMSCLIENTCONTACT, Trans).ConfigureAwait(false); await _QueryExecutor.CommitAsync(Trans).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( contact.EngagementId, EntityConstant.OBJECTIDMSCLIENTCONTACT, CacheKeyLevel.CLIENT_LEVEL, login); await _KeyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.UpdateSuccess; } catch (Exception) { await _QueryExecutor.RollbackAsync(Trans).ConfigureAwait(false); throw; } } }